aboutsummaryrefslogtreecommitdiffstats
path: root/fs/cifs/cifsfs.c
diff options
context:
space:
mode:
authorSteve French <sfrench@us.ibm.com>2011-05-26 23:50:55 -0400
committerSteve French <sfrench@us.ibm.com>2011-05-26 23:50:55 -0400
commitf87d39d951329cd8f462bf9007d334122c0599d0 (patch)
treeba4c4d9dee6958c7d8ee87070a58d80389be2d2f /fs/cifs/cifsfs.c
parent641a58d66d086327042e9d73c6606fd02c8f067c (diff)
[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>
Diffstat (limited to 'fs/cifs/cifsfs.c')
-rw-r--r--fs/cifs/cifsfs.c101
1 files changed, 98 insertions, 3 deletions
diff --git a/fs/cifs/cifsfs.c b/fs/cifs/cifsfs.c
index 1d2a93c60e75..46fdd55cf427 100644
--- a/fs/cifs/cifsfs.c
+++ b/fs/cifs/cifsfs.c
@@ -415,8 +415,6 @@ cifs_show_options(struct seq_file *s, struct vfsmount *m)
415 seq_printf(s, ",nocase"); 415 seq_printf(s, ",nocase");
416 if (tcon->retry) 416 if (tcon->retry)
417 seq_printf(s, ",hard"); 417 seq_printf(s, ",hard");
418 if (cifs_sb->prepath)
419 seq_printf(s, ",prepath=%s", cifs_sb->prepath);
420 if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_POSIX_PATHS) 418 if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_POSIX_PATHS)
421 seq_printf(s, ",posixpaths"); 419 seq_printf(s, ",posixpaths");
422 if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_SET_UID) 420 if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_SET_UID)
@@ -530,6 +528,100 @@ static const struct super_operations cifs_super_ops = {
530#endif 528#endif
531}; 529};
532 530
531/*
532 * Get root dentry from superblock according to prefix path mount option.
533 * Return dentry with refcount + 1 on success and NULL otherwise.
534 */
535static struct dentry *
536cifs_get_root(struct smb_vol *vol, struct super_block *sb)
537{
538 int xid, rc;
539 struct inode *inode;
540 struct qstr name;
541 struct dentry *dparent = NULL, *dchild = NULL, *alias;
542 struct cifs_sb_info *cifs_sb = CIFS_SB(sb);
543 unsigned int i, full_len, len;
544 char *full_path = NULL, *pstart;
545 char sep;
546
547 full_path = cifs_build_path_to_root(vol, cifs_sb,
548 cifs_sb_master_tcon(cifs_sb));
549 if (full_path == NULL)
550 return NULL;
551
552 cFYI(1, "Get root dentry for %s", full_path);
553
554 xid = GetXid();
555 sep = CIFS_DIR_SEP(cifs_sb);
556 dparent = dget(sb->s_root);
557 full_len = strlen(full_path);
558 full_path[full_len] = sep;
559 pstart = full_path + 1;
560
561 for (i = 1, len = 0; i <= full_len; i++) {
562 if (full_path[i] != sep || !len) {
563 len++;
564 continue;
565 }
566
567 full_path[i] = 0;
568 cFYI(1, "get dentry for %s", pstart);
569
570 name.name = pstart;
571 name.len = len;
572 name.hash = full_name_hash(pstart, len);
573 dchild = d_lookup(dparent, &name);
574 if (dchild == NULL) {
575 cFYI(1, "not exists");
576 dchild = d_alloc(dparent, &name);
577 if (dchild == NULL) {
578 dput(dparent);
579 dparent = NULL;
580 goto out;
581 }
582 }
583
584 cFYI(1, "get inode");
585 if (dchild->d_inode == NULL) {
586 cFYI(1, "not exists");
587 inode = NULL;
588 if (cifs_sb_master_tcon(CIFS_SB(sb))->unix_ext)
589 rc = cifs_get_inode_info_unix(&inode, full_path,
590 sb, xid);
591 else
592 rc = cifs_get_inode_info(&inode, full_path,
593 NULL, sb, xid, NULL);
594 if (rc) {
595 dput(dchild);
596 dput(dparent);
597 dparent = NULL;
598 goto out;
599 }
600 alias = d_materialise_unique(dchild, inode);
601 if (alias != NULL) {
602 dput(dchild);
603 if (IS_ERR(alias)) {
604 dput(dparent);
605 dparent = NULL;
606 goto out;
607 }
608 dchild = alias;
609 }
610 }
611 cFYI(1, "parent %p, child %p", dparent, dchild);
612
613 dput(dparent);
614 dparent = dchild;
615 len = 0;
616 pstart = full_path + i + 1;
617 full_path[i] = sep;
618 }
619out:
620 _FreeXid(xid);
621 kfree(full_path);
622 return dparent;
623}
624
533static struct dentry * 625static struct dentry *
534cifs_do_mount(struct file_system_type *fs_type, 626cifs_do_mount(struct file_system_type *fs_type,
535 int flags, const char *dev_name, void *data) 627 int flags, const char *dev_name, void *data)
@@ -585,7 +677,10 @@ cifs_do_mount(struct file_system_type *fs_type,
585 677
586 sb->s_flags |= MS_ACTIVE; 678 sb->s_flags |= MS_ACTIVE;
587 679
588 root = dget(sb->s_root); 680 root = cifs_get_root(volume_info, sb);
681 if (root == NULL)
682 goto out_super;
683 cFYI(1, "dentry root is: %p", root);
589 goto out; 684 goto out;
590 685
591out_super: 686out_super: