Re: [PATCH 3/4] CIFS: Migrate from prefixpath logic

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



2011/4/29 Jeff Layton <jlayton@xxxxxxxxxx>:
> On Fri, 15 Apr 2011 11:01:55 +0400
> Pavel Shilovsky <piastry@xxxxxxxxxxx> wrote:
>
>> 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.
>>
>> Signed-off-by: Pavel Shilovsky <piastry@xxxxxxxxxxx>
>> ---
>>  fs/cifs/cifs_fs_sb.h |    2 -
>>  fs/cifs/cifsfs.c     |   95 +++++++++++++++++++++++++++++++++++-
>>  fs/cifs/cifsglob.h   |   76 +++++++++++++++++++++++++++++
>>  fs/cifs/cifsproto.h  |    5 +-
>>  fs/cifs/connect.c    |  129 ++------------------------------------------------
>>  fs/cifs/dir.c        |    7 +--
>>  fs/cifs/inode.c      |   15 +++---
>>  7 files changed, 186 insertions(+), 143 deletions(-)
>>
>> diff --git a/fs/cifs/cifs_fs_sb.h b/fs/cifs/cifs_fs_sb.h
>> index adecd36..a18ba37 100644
>> --- a/fs/cifs/cifs_fs_sb.h
>> +++ b/fs/cifs/cifs_fs_sb.h
>> @@ -58,8 +58,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;
>> diff --git a/fs/cifs/cifsfs.c b/fs/cifs/cifsfs.c
>> index 3227db6..44394c8 100644
>> --- a/fs/cifs/cifsfs.c
>> +++ b/fs/cifs/cifsfs.c
>> @@ -434,8 +434,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)
>> @@ -549,6 +547,92 @@ 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;
>> +     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;
>> +                     }
>> +                     d_add(dchild, inode);
>                        ^^^^^^
>                        Is this racy? Could another dentry have been
>                        added between the time that you did the initial
>                        lookup and here? I think there are functions
>                        that guard against that possibility.
>                        d_materialise_unique maybe?
>
>> +             }
>> +             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);
>> +     full_path[full_len] = 0;
>        ^^^ that's unnecessary, you free this just afterward.
>
>> +     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)
>> @@ -603,7 +687,12 @@ 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) {
>> +             kfree(copied_data);
>> +             goto err_out;
>> +     }
>> +     cFYI(1, "dentry root is: %p", root);
>>  out:
>>       cifs_cleanup_volume_info(&volume_info);
>>       return root;
>
> [...]
>
>> @@ -887,16 +887,17 @@ struct inode *cifs_root_iget(struct super_block *sb)
>>       char *full_path;
>>       struct cifs_tcon *tcon = cifs_sb_master_tcon(cifs_sb);
>>
>> -     full_path = cifs_build_path_to_root(cifs_sb, tcon);
>> +     full_path = kmalloc(1, GFP_KERNEL);
>>       if (full_path == NULL)
>>               return ERR_PTR(-ENOMEM);
>> +     full_path[0] = 0;
>>
>
> Don't kmalloc 1 byte, just pass "" or do it on the stack instead.
>
>>       xid = GetXid();
>>       if (tcon->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);
>> +             rc = cifs_get_inode_info(&inode, full_path, NULL, sb, xid,
>> +                                      NULL);
>>
>>       if (!inode) {
>>               inode = ERR_PTR(rc);
>
>
> --
> Jeff Layton <jlayton@xxxxxxxxxx>
>

Thanks! Good points - I will respin this patch.

-- 
Best regards,
Pavel Shilovsky.
--
To unsubscribe from this list: send the line "unsubscribe linux-cifs" in
the body of a message to majordomo@xxxxxxxxxxxxxxx
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[Linux USB Devel]     [Video for Linux]     [Linux Audio Users]     [Yosemite News]     [Linux Kernel]     [Linux SCSI]

  Powered by Linux