Commit f6a9bc33 authored by Al Viro's avatar Al Viro Committed by Steve French

cifs: allocate buffer in the caller of build_path_from_dentry()

build_path_from_dentry() open-codes dentry_path_raw().  The reason
we can't use dentry_path_raw() in there (and postprocess the
result as needed) is that the callers of build_path_from_dentry()
expect that the object to be freed on cleanup and the string to
be used are at the same address.  That's painful, since the path
is naturally built end-to-beginning - we start at the leaf and
go through the ancestors, accumulating the pathname.

Life would be easier if we left the buffer allocation to callers.
It wouldn't be exact-sized buffer, but none of the callers keep
the result for long - it's always freed before the caller returns.
So there's no need to do exact-sized allocation; better use
__getname()/__putname(), same as we do for pathname arguments
of syscalls.  What's more, there's no need to do allocation under
spinlocks, so GFP_ATOMIC is not needed.

Next patch will replace the open-coded dentry_path_raw() (in
build_path_from_dentry_optional_prefix()) with calling the real
thing.  This patch only introduces wrappers for allocating/freeing
the buffers and switches to new calling conventions:
	build_path_from_dentry(dentry, buf)
expects buf to be address of a page-sized object or NULL,
return value is a pathname built inside that buffer on success,
ERR_PTR(-ENOMEM) if buf is NULL and ERR_PTR(-ENAMETOOLONG) if
the pathname won't fit into page.  Note that we don't need to
check for failure when allocating the buffer in the caller -
build_path_from_dentry() will do the right thing.
Signed-off-by: default avatarAl Viro <viro@zeniv.linux.org.uk>
Signed-off-by: default avatarSteve French <stfrench@microsoft.com>
parent 8e33cf20
...@@ -302,6 +302,7 @@ static struct vfsmount *cifs_dfs_do_automount(struct dentry *mntpt) ...@@ -302,6 +302,7 @@ static struct vfsmount *cifs_dfs_do_automount(struct dentry *mntpt)
struct cifs_sb_info *cifs_sb; struct cifs_sb_info *cifs_sb;
struct cifs_ses *ses; struct cifs_ses *ses;
struct cifs_tcon *tcon; struct cifs_tcon *tcon;
void *page;
char *full_path, *root_path; char *full_path, *root_path;
unsigned int xid; unsigned int xid;
int rc; int rc;
...@@ -324,10 +325,13 @@ static struct vfsmount *cifs_dfs_do_automount(struct dentry *mntpt) ...@@ -324,10 +325,13 @@ static struct vfsmount *cifs_dfs_do_automount(struct dentry *mntpt)
goto cdda_exit; goto cdda_exit;
} }
page = alloc_dentry_path();
/* always use tree name prefix */ /* always use tree name prefix */
full_path = build_path_from_dentry_optional_prefix(mntpt, true); full_path = build_path_from_dentry_optional_prefix(mntpt, page, true);
if (full_path == NULL) if (IS_ERR(full_path)) {
goto cdda_exit; mnt = ERR_CAST(full_path);
goto free_full_path;
}
convert_delimiter(full_path, '\\'); convert_delimiter(full_path, '\\');
...@@ -385,7 +389,7 @@ static struct vfsmount *cifs_dfs_do_automount(struct dentry *mntpt) ...@@ -385,7 +389,7 @@ static struct vfsmount *cifs_dfs_do_automount(struct dentry *mntpt)
free_root_path: free_root_path:
kfree(root_path); kfree(root_path);
free_full_path: free_full_path:
kfree(full_path); free_dentry_path(page);
cdda_exit: cdda_exit:
cifs_dbg(FYI, "leaving %s\n" , __func__); cifs_dbg(FYI, "leaving %s\n" , __func__);
return mnt; return mnt;
......
...@@ -69,9 +69,20 @@ extern int init_cifs_idmap(void); ...@@ -69,9 +69,20 @@ extern int init_cifs_idmap(void);
extern void exit_cifs_idmap(void); extern void exit_cifs_idmap(void);
extern int init_cifs_spnego(void); extern int init_cifs_spnego(void);
extern void exit_cifs_spnego(void); extern void exit_cifs_spnego(void);
extern const char *build_path_from_dentry(struct dentry *); extern const char *build_path_from_dentry(struct dentry *, void *);
extern char *build_path_from_dentry_optional_prefix(struct dentry *direntry, extern char *build_path_from_dentry_optional_prefix(struct dentry *direntry,
bool prefix); void *page, bool prefix);
static inline void *alloc_dentry_path(void)
{
return __getname();
}
static inline void free_dentry_path(void *page)
{
if (page)
__putname(page);
}
extern char *cifs_build_path_to_root(struct smb3_fs_context *ctx, extern char *cifs_build_path_to_root(struct smb3_fs_context *ctx,
struct cifs_sb_info *cifs_sb, struct cifs_sb_info *cifs_sb,
struct cifs_tcon *tcon, struct cifs_tcon *tcon,
......
...@@ -79,29 +79,33 @@ cifs_build_path_to_root(struct smb3_fs_context *ctx, struct cifs_sb_info *cifs_s ...@@ -79,29 +79,33 @@ cifs_build_path_to_root(struct smb3_fs_context *ctx, struct cifs_sb_info *cifs_s
/* Note: caller must free return buffer */ /* Note: caller must free return buffer */
const char * const char *
build_path_from_dentry(struct dentry *direntry) build_path_from_dentry(struct dentry *direntry, void *page)
{ {
struct cifs_sb_info *cifs_sb = CIFS_SB(direntry->d_sb); struct cifs_sb_info *cifs_sb = CIFS_SB(direntry->d_sb);
struct cifs_tcon *tcon = cifs_sb_master_tcon(cifs_sb); struct cifs_tcon *tcon = cifs_sb_master_tcon(cifs_sb);
bool prefix = tcon->Flags & SMB_SHARE_IS_IN_DFS; bool prefix = tcon->Flags & SMB_SHARE_IS_IN_DFS;
return build_path_from_dentry_optional_prefix(direntry, return build_path_from_dentry_optional_prefix(direntry, page,
prefix); prefix);
} }
char * char *
build_path_from_dentry_optional_prefix(struct dentry *direntry, bool prefix) build_path_from_dentry_optional_prefix(struct dentry *direntry, void *page,
bool prefix)
{ {
struct dentry *temp; struct dentry *temp;
int namelen; int namelen;
int dfsplen; int dfsplen;
int pplen = 0; int pplen = 0;
char *full_path; char *full_path = page;
char dirsep; char dirsep;
struct cifs_sb_info *cifs_sb = CIFS_SB(direntry->d_sb); struct cifs_sb_info *cifs_sb = CIFS_SB(direntry->d_sb);
struct cifs_tcon *tcon = cifs_sb_master_tcon(cifs_sb); struct cifs_tcon *tcon = cifs_sb_master_tcon(cifs_sb);
unsigned seq; unsigned seq;
if (unlikely(!page))
return ERR_PTR(-ENOMEM);
dirsep = CIFS_DIR_SEP(cifs_sb); dirsep = CIFS_DIR_SEP(cifs_sb);
if (prefix) if (prefix)
dfsplen = strnlen(tcon->treeName, MAX_TREE_SIZE + 1); dfsplen = strnlen(tcon->treeName, MAX_TREE_SIZE + 1);
...@@ -118,17 +122,12 @@ build_path_from_dentry_optional_prefix(struct dentry *direntry, bool prefix) ...@@ -118,17 +122,12 @@ build_path_from_dentry_optional_prefix(struct dentry *direntry, bool prefix)
for (temp = direntry; !IS_ROOT(temp);) { for (temp = direntry; !IS_ROOT(temp);) {
namelen += (1 + temp->d_name.len); namelen += (1 + temp->d_name.len);
temp = temp->d_parent; temp = temp->d_parent;
if (temp == NULL) {
cifs_dbg(VFS, "corrupt dentry\n");
rcu_read_unlock();
return NULL;
}
} }
rcu_read_unlock(); rcu_read_unlock();
full_path = kmalloc(namelen+1, GFP_ATOMIC); if (namelen >= PAGE_SIZE)
if (full_path == NULL) return ERR_PTR(-ENAMETOOLONG);
return full_path;
full_path[namelen] = 0; /* trailing null */ full_path[namelen] = 0; /* trailing null */
rcu_read_lock(); rcu_read_lock();
for (temp = direntry; !IS_ROOT(temp);) { for (temp = direntry; !IS_ROOT(temp);) {
...@@ -145,12 +144,6 @@ build_path_from_dentry_optional_prefix(struct dentry *direntry, bool prefix) ...@@ -145,12 +144,6 @@ build_path_from_dentry_optional_prefix(struct dentry *direntry, bool prefix)
} }
spin_unlock(&temp->d_lock); spin_unlock(&temp->d_lock);
temp = temp->d_parent; temp = temp->d_parent;
if (temp == NULL) {
cifs_dbg(VFS, "corrupt dentry\n");
rcu_read_unlock();
kfree(full_path);
return NULL;
}
} }
rcu_read_unlock(); rcu_read_unlock();
if (namelen != dfsplen + pplen || read_seqretry(&rename_lock, seq)) { if (namelen != dfsplen + pplen || read_seqretry(&rename_lock, seq)) {
...@@ -159,7 +152,6 @@ build_path_from_dentry_optional_prefix(struct dentry *direntry, bool prefix) ...@@ -159,7 +152,6 @@ build_path_from_dentry_optional_prefix(struct dentry *direntry, bool prefix)
/* presumably this is only possible if racing with a rename /* presumably this is only possible if racing with a rename
of one of the parent directories (we can not lock the dentries of one of the parent directories (we can not lock the dentries
above us to prevent this, but retrying should be harmless) */ above us to prevent this, but retrying should be harmless) */
kfree(full_path);
goto cifs_bp_rename_retry; goto cifs_bp_rename_retry;
} }
/* DIR_SEP already set for byte 0 / vs \ but not for /* DIR_SEP already set for byte 0 / vs \ but not for
...@@ -233,7 +225,8 @@ cifs_do_create(struct inode *inode, struct dentry *direntry, unsigned int xid, ...@@ -233,7 +225,8 @@ cifs_do_create(struct inode *inode, struct dentry *direntry, unsigned int xid,
int desired_access; int desired_access;
struct cifs_sb_info *cifs_sb = CIFS_SB(inode->i_sb); struct cifs_sb_info *cifs_sb = CIFS_SB(inode->i_sb);
struct cifs_tcon *tcon = tlink_tcon(tlink); struct cifs_tcon *tcon = tlink_tcon(tlink);
const char *full_path = NULL; const char *full_path;
void *page = alloc_dentry_path();
FILE_ALL_INFO *buf = NULL; FILE_ALL_INFO *buf = NULL;
struct inode *newinode = NULL; struct inode *newinode = NULL;
int disposition; int disposition;
...@@ -244,9 +237,11 @@ cifs_do_create(struct inode *inode, struct dentry *direntry, unsigned int xid, ...@@ -244,9 +237,11 @@ cifs_do_create(struct inode *inode, struct dentry *direntry, unsigned int xid,
if (tcon->ses->server->oplocks) if (tcon->ses->server->oplocks)
*oplock = REQ_OPLOCK; *oplock = REQ_OPLOCK;
full_path = build_path_from_dentry(direntry); full_path = build_path_from_dentry(direntry, page);
if (!full_path) if (IS_ERR(full_path)) {
return -ENOMEM; free_dentry_path(page);
return PTR_ERR(full_path);
}
if (tcon->unix_ext && cap_unix(tcon->ses) && !tcon->broken_posix_open && if (tcon->unix_ext && cap_unix(tcon->ses) && !tcon->broken_posix_open &&
(CIFS_UNIX_POSIX_PATH_OPS_CAP & (CIFS_UNIX_POSIX_PATH_OPS_CAP &
...@@ -448,7 +443,7 @@ cifs_do_create(struct inode *inode, struct dentry *direntry, unsigned int xid, ...@@ -448,7 +443,7 @@ cifs_do_create(struct inode *inode, struct dentry *direntry, unsigned int xid,
out: out:
kfree(buf); kfree(buf);
kfree(full_path); free_dentry_path(page);
return rc; return rc;
out_err: out_err:
...@@ -619,7 +614,8 @@ int cifs_mknod(struct user_namespace *mnt_userns, struct inode *inode, ...@@ -619,7 +614,8 @@ int cifs_mknod(struct user_namespace *mnt_userns, struct inode *inode,
struct cifs_sb_info *cifs_sb; struct cifs_sb_info *cifs_sb;
struct tcon_link *tlink; struct tcon_link *tlink;
struct cifs_tcon *tcon; struct cifs_tcon *tcon;
const char *full_path = NULL; const char *full_path;
void *page;
if (!old_valid_dev(device_number)) if (!old_valid_dev(device_number))
return -EINVAL; return -EINVAL;
...@@ -629,13 +625,13 @@ int cifs_mknod(struct user_namespace *mnt_userns, struct inode *inode, ...@@ -629,13 +625,13 @@ int cifs_mknod(struct user_namespace *mnt_userns, struct inode *inode,
if (IS_ERR(tlink)) if (IS_ERR(tlink))
return PTR_ERR(tlink); return PTR_ERR(tlink);
page = alloc_dentry_path();
tcon = tlink_tcon(tlink); tcon = tlink_tcon(tlink);
xid = get_xid(); xid = get_xid();
full_path = build_path_from_dentry(direntry); full_path = build_path_from_dentry(direntry, page);
if (full_path == NULL) { if (IS_ERR(full_path)) {
rc = -ENOMEM; rc = PTR_ERR(full_path);
goto mknod_out; goto mknod_out;
} }
...@@ -644,7 +640,7 @@ int cifs_mknod(struct user_namespace *mnt_userns, struct inode *inode, ...@@ -644,7 +640,7 @@ int cifs_mknod(struct user_namespace *mnt_userns, struct inode *inode,
device_number); device_number);
mknod_out: mknod_out:
kfree(full_path); free_dentry_path(page);
free_xid(xid); free_xid(xid);
cifs_put_tlink(tlink); cifs_put_tlink(tlink);
return rc; return rc;
...@@ -660,7 +656,8 @@ cifs_lookup(struct inode *parent_dir_inode, struct dentry *direntry, ...@@ -660,7 +656,8 @@ cifs_lookup(struct inode *parent_dir_inode, struct dentry *direntry,
struct tcon_link *tlink; struct tcon_link *tlink;
struct cifs_tcon *pTcon; struct cifs_tcon *pTcon;
struct inode *newInode = NULL; struct inode *newInode = NULL;
const char *full_path = NULL; const char *full_path;
void *page;
xid = get_xid(); xid = get_xid();
...@@ -687,11 +684,13 @@ cifs_lookup(struct inode *parent_dir_inode, struct dentry *direntry, ...@@ -687,11 +684,13 @@ cifs_lookup(struct inode *parent_dir_inode, struct dentry *direntry,
/* can not grab the rename sem here since it would /* can not grab the rename sem here since it would
deadlock in the cases (beginning of sys_rename itself) deadlock in the cases (beginning of sys_rename itself)
in which we already have the sb rename sem */ in which we already have the sb rename sem */
full_path = build_path_from_dentry(direntry); page = alloc_dentry_path();
if (full_path == NULL) { full_path = build_path_from_dentry(direntry, page);
if (IS_ERR(full_path)) {
cifs_put_tlink(tlink); cifs_put_tlink(tlink);
free_xid(xid); free_xid(xid);
return ERR_PTR(-ENOMEM); free_dentry_path(page);
return ERR_CAST(full_path);
} }
if (d_really_is_positive(direntry)) { if (d_really_is_positive(direntry)) {
...@@ -727,7 +726,7 @@ cifs_lookup(struct inode *parent_dir_inode, struct dentry *direntry, ...@@ -727,7 +726,7 @@ cifs_lookup(struct inode *parent_dir_inode, struct dentry *direntry,
} }
newInode = ERR_PTR(rc); newInode = ERR_PTR(rc);
} }
kfree(full_path); free_dentry_path(page);
cifs_put_tlink(tlink); cifs_put_tlink(tlink);
free_xid(xid); free_xid(xid);
return d_splice_alias(newInode, direntry); return d_splice_alias(newInode, direntry);
......
...@@ -530,7 +530,8 @@ int cifs_open(struct inode *inode, struct file *file) ...@@ -530,7 +530,8 @@ int cifs_open(struct inode *inode, struct file *file)
struct cifs_tcon *tcon; struct cifs_tcon *tcon;
struct tcon_link *tlink; struct tcon_link *tlink;
struct cifsFileInfo *cfile = NULL; struct cifsFileInfo *cfile = NULL;
const char *full_path = NULL; void *page;
const char *full_path;
bool posix_open_ok = false; bool posix_open_ok = false;
struct cifs_fid fid; struct cifs_fid fid;
struct cifs_pending_open open; struct cifs_pending_open open;
...@@ -546,9 +547,10 @@ int cifs_open(struct inode *inode, struct file *file) ...@@ -546,9 +547,10 @@ int cifs_open(struct inode *inode, struct file *file)
tcon = tlink_tcon(tlink); tcon = tlink_tcon(tlink);
server = tcon->ses->server; server = tcon->ses->server;
full_path = build_path_from_dentry(file_dentry(file)); page = alloc_dentry_path();
if (full_path == NULL) { full_path = build_path_from_dentry(file_dentry(file), page);
rc = -ENOMEM; if (IS_ERR(full_path)) {
rc = PTR_ERR(full_path);
goto out; goto out;
} }
...@@ -640,7 +642,7 @@ int cifs_open(struct inode *inode, struct file *file) ...@@ -640,7 +642,7 @@ int cifs_open(struct inode *inode, struct file *file)
} }
out: out:
kfree(full_path); free_dentry_path(page);
free_xid(xid); free_xid(xid);
cifs_put_tlink(tlink); cifs_put_tlink(tlink);
return rc; return rc;
...@@ -689,7 +691,8 @@ cifs_reopen_file(struct cifsFileInfo *cfile, bool can_flush) ...@@ -689,7 +691,8 @@ cifs_reopen_file(struct cifsFileInfo *cfile, bool can_flush)
struct TCP_Server_Info *server; struct TCP_Server_Info *server;
struct cifsInodeInfo *cinode; struct cifsInodeInfo *cinode;
struct inode *inode; struct inode *inode;
const char *full_path = NULL; void *page;
const char *full_path;
int desired_access; int desired_access;
int disposition = FILE_OPEN; int disposition = FILE_OPEN;
int create_options = CREATE_NOT_DIR; int create_options = CREATE_NOT_DIR;
...@@ -699,9 +702,8 @@ cifs_reopen_file(struct cifsFileInfo *cfile, bool can_flush) ...@@ -699,9 +702,8 @@ cifs_reopen_file(struct cifsFileInfo *cfile, bool can_flush)
mutex_lock(&cfile->fh_mutex); mutex_lock(&cfile->fh_mutex);
if (!cfile->invalidHandle) { if (!cfile->invalidHandle) {
mutex_unlock(&cfile->fh_mutex); mutex_unlock(&cfile->fh_mutex);
rc = 0;
free_xid(xid); free_xid(xid);
return rc; return 0;
} }
inode = d_inode(cfile->dentry); inode = d_inode(cfile->dentry);
...@@ -715,12 +717,13 @@ cifs_reopen_file(struct cifsFileInfo *cfile, bool can_flush) ...@@ -715,12 +717,13 @@ cifs_reopen_file(struct cifsFileInfo *cfile, bool can_flush)
* called and if the server was down that means we end up here, and we * called and if the server was down that means we end up here, and we
* can never tell if the caller already has the rename_sem. * can never tell if the caller already has the rename_sem.
*/ */
full_path = build_path_from_dentry(cfile->dentry); page = alloc_dentry_path();
if (full_path == NULL) { full_path = build_path_from_dentry(cfile->dentry, page);
rc = -ENOMEM; if (IS_ERR(full_path)) {
mutex_unlock(&cfile->fh_mutex); mutex_unlock(&cfile->fh_mutex);
free_dentry_path(page);
free_xid(xid); free_xid(xid);
return rc; return PTR_ERR(full_path);
} }
cifs_dbg(FYI, "inode = 0x%p file flags 0x%x for %s\n", cifs_dbg(FYI, "inode = 0x%p file flags 0x%x for %s\n",
...@@ -838,7 +841,7 @@ cifs_reopen_file(struct cifsFileInfo *cfile, bool can_flush) ...@@ -838,7 +841,7 @@ cifs_reopen_file(struct cifsFileInfo *cfile, bool can_flush)
cifs_relock_file(cfile); cifs_relock_file(cfile);
reopen_error_exit: reopen_error_exit:
kfree(full_path); free_dentry_path(page);
free_xid(xid); free_xid(xid);
return rc; return rc;
} }
...@@ -2069,34 +2072,31 @@ cifs_get_writable_path(struct cifs_tcon *tcon, const char *name, ...@@ -2069,34 +2072,31 @@ cifs_get_writable_path(struct cifs_tcon *tcon, const char *name,
int flags, int flags,
struct cifsFileInfo **ret_file) struct cifsFileInfo **ret_file)
{ {
struct list_head *tmp;
struct cifsFileInfo *cfile; struct cifsFileInfo *cfile;
struct cifsInodeInfo *cinode; void *page = alloc_dentry_path();
const char *full_path;
*ret_file = NULL; *ret_file = NULL;
spin_lock(&tcon->open_file_lock); spin_lock(&tcon->open_file_lock);
list_for_each(tmp, &tcon->openFileList) { list_for_each_entry(cfile, &tcon->openFileList, tlist) {
cfile = list_entry(tmp, struct cifsFileInfo, struct cifsInodeInfo *cinode;
tlist); const char *full_path = build_path_from_dentry(cfile->dentry, page);
full_path = build_path_from_dentry(cfile->dentry); if (IS_ERR(full_path)) {
if (full_path == NULL) {
spin_unlock(&tcon->open_file_lock); spin_unlock(&tcon->open_file_lock);
return -ENOMEM; free_dentry_path(page);
return PTR_ERR(full_path);
} }
if (strcmp(full_path, name)) { if (strcmp(full_path, name))
kfree(full_path);
continue; continue;
}
kfree(full_path);
cinode = CIFS_I(d_inode(cfile->dentry)); cinode = CIFS_I(d_inode(cfile->dentry));
spin_unlock(&tcon->open_file_lock); spin_unlock(&tcon->open_file_lock);
free_dentry_path(page);
return cifs_get_writable_file(cinode, flags, ret_file); return cifs_get_writable_file(cinode, flags, ret_file);
} }
spin_unlock(&tcon->open_file_lock); spin_unlock(&tcon->open_file_lock);
free_dentry_path(page);
return -ENOENT; return -ENOENT;
} }
...@@ -2104,35 +2104,32 @@ int ...@@ -2104,35 +2104,32 @@ int
cifs_get_readable_path(struct cifs_tcon *tcon, const char *name, cifs_get_readable_path(struct cifs_tcon *tcon, const char *name,
struct cifsFileInfo **ret_file) struct cifsFileInfo **ret_file)
{ {
struct list_head *tmp;
struct cifsFileInfo *cfile; struct cifsFileInfo *cfile;
struct cifsInodeInfo *cinode; void *page = alloc_dentry_path();
const char *full_path;
*ret_file = NULL; *ret_file = NULL;
spin_lock(&tcon->open_file_lock); spin_lock(&tcon->open_file_lock);
list_for_each(tmp, &tcon->openFileList) { list_for_each_entry(cfile, &tcon->openFileList, tlist) {
cfile = list_entry(tmp, struct cifsFileInfo, struct cifsInodeInfo *cinode;
tlist); const char *full_path = build_path_from_dentry(cfile->dentry, page);
full_path = build_path_from_dentry(cfile->dentry); if (IS_ERR(full_path)) {
if (full_path == NULL) {
spin_unlock(&tcon->open_file_lock); spin_unlock(&tcon->open_file_lock);
return -ENOMEM; free_dentry_path(page);
return PTR_ERR(full_path);
} }
if (strcmp(full_path, name)) { if (strcmp(full_path, name))
kfree(full_path);
continue; continue;
}
kfree(full_path);
cinode = CIFS_I(d_inode(cfile->dentry)); cinode = CIFS_I(d_inode(cfile->dentry));
spin_unlock(&tcon->open_file_lock); spin_unlock(&tcon->open_file_lock);
free_dentry_path(page);
*ret_file = find_readable_file(cinode, 0); *ret_file = find_readable_file(cinode, 0);
return *ret_file ? 0 : -ENOENT; return *ret_file ? 0 : -ENOENT;
} }
spin_unlock(&tcon->open_file_lock); spin_unlock(&tcon->open_file_lock);
free_dentry_path(page);
return -ENOENT; return -ENOENT;
} }
......
...@@ -1609,7 +1609,8 @@ int cifs_unlink(struct inode *dir, struct dentry *dentry) ...@@ -1609,7 +1609,8 @@ int cifs_unlink(struct inode *dir, struct dentry *dentry)
{ {
int rc = 0; int rc = 0;
unsigned int xid; unsigned int xid;
const char *full_path = NULL; const char *full_path;
void *page;
struct inode *inode = d_inode(dentry); struct inode *inode = d_inode(dentry);
struct cifsInodeInfo *cifs_inode; struct cifsInodeInfo *cifs_inode;
struct super_block *sb = dir->i_sb; struct super_block *sb = dir->i_sb;
...@@ -1629,6 +1630,7 @@ int cifs_unlink(struct inode *dir, struct dentry *dentry) ...@@ -1629,6 +1630,7 @@ int cifs_unlink(struct inode *dir, struct dentry *dentry)
server = tcon->ses->server; server = tcon->ses->server;
xid = get_xid(); xid = get_xid();
page = alloc_dentry_path();
if (tcon->nodelete) { if (tcon->nodelete) {
rc = -EACCES; rc = -EACCES;
...@@ -1637,9 +1639,9 @@ int cifs_unlink(struct inode *dir, struct dentry *dentry) ...@@ -1637,9 +1639,9 @@ int cifs_unlink(struct inode *dir, struct dentry *dentry)
/* Unlink can be called from rename so we can not take the /* Unlink can be called from rename so we can not take the
* sb->s_vfs_rename_mutex here */ * sb->s_vfs_rename_mutex here */
full_path = build_path_from_dentry(dentry); full_path = build_path_from_dentry(dentry, page);
if (full_path == NULL) { if (IS_ERR(full_path)) {
rc = -ENOMEM; rc = PTR_ERR(full_path);
goto unlink_out; goto unlink_out;
} }
...@@ -1713,7 +1715,7 @@ int cifs_unlink(struct inode *dir, struct dentry *dentry) ...@@ -1713,7 +1715,7 @@ int cifs_unlink(struct inode *dir, struct dentry *dentry)
cifs_inode = CIFS_I(dir); cifs_inode = CIFS_I(dir);
CIFS_I(dir)->time = 0; /* force revalidate of dir as well */ CIFS_I(dir)->time = 0; /* force revalidate of dir as well */
unlink_out: unlink_out:
kfree(full_path); free_dentry_path(page);
kfree(attrs); kfree(attrs);
free_xid(xid); free_xid(xid);
cifs_put_tlink(tlink); cifs_put_tlink(tlink);
...@@ -1867,6 +1869,7 @@ int cifs_mkdir(struct user_namespace *mnt_userns, struct inode *inode, ...@@ -1867,6 +1869,7 @@ int cifs_mkdir(struct user_namespace *mnt_userns, struct inode *inode,
struct cifs_tcon *tcon; struct cifs_tcon *tcon;
struct TCP_Server_Info *server; struct TCP_Server_Info *server;
const char *full_path; const char *full_path;
void *page;
cifs_dbg(FYI, "In cifs_mkdir, mode = %04ho inode = 0x%p\n", cifs_dbg(FYI, "In cifs_mkdir, mode = %04ho inode = 0x%p\n",
mode, inode); mode, inode);
...@@ -1879,9 +1882,10 @@ int cifs_mkdir(struct user_namespace *mnt_userns, struct inode *inode, ...@@ -1879,9 +1882,10 @@ int cifs_mkdir(struct user_namespace *mnt_userns, struct inode *inode,
xid = get_xid(); xid = get_xid();
full_path = build_path_from_dentry(direntry); page = alloc_dentry_path();
if (full_path == NULL) { full_path = build_path_from_dentry(direntry, page);
rc = -ENOMEM; if (IS_ERR(full_path)) {
rc = PTR_ERR(full_path);
goto mkdir_out; goto mkdir_out;
} }
...@@ -1924,7 +1928,7 @@ int cifs_mkdir(struct user_namespace *mnt_userns, struct inode *inode, ...@@ -1924,7 +1928,7 @@ int cifs_mkdir(struct user_namespace *mnt_userns, struct inode *inode,
* attributes are invalid now. * attributes are invalid now.
*/ */
CIFS_I(inode)->time = 0; CIFS_I(inode)->time = 0;
kfree(full_path); free_dentry_path(page);
free_xid(xid); free_xid(xid);
cifs_put_tlink(tlink); cifs_put_tlink(tlink);
return rc; return rc;
...@@ -1938,16 +1942,17 @@ int cifs_rmdir(struct inode *inode, struct dentry *direntry) ...@@ -1938,16 +1942,17 @@ int cifs_rmdir(struct inode *inode, struct dentry *direntry)
struct tcon_link *tlink; struct tcon_link *tlink;
struct cifs_tcon *tcon; struct cifs_tcon *tcon;
struct TCP_Server_Info *server; struct TCP_Server_Info *server;
const char *full_path = NULL; const char *full_path;
void *page = alloc_dentry_path();
struct cifsInodeInfo *cifsInode; struct cifsInodeInfo *cifsInode;
cifs_dbg(FYI, "cifs_rmdir, inode = 0x%p\n", inode); cifs_dbg(FYI, "cifs_rmdir, inode = 0x%p\n", inode);
xid = get_xid(); xid = get_xid();
full_path = build_path_from_dentry(direntry); full_path = build_path_from_dentry(direntry, page);
if (full_path == NULL) { if (IS_ERR(full_path)) {
rc = -ENOMEM; rc = PTR_ERR(full_path);
goto rmdir_exit; goto rmdir_exit;
} }
...@@ -1997,7 +2002,7 @@ int cifs_rmdir(struct inode *inode, struct dentry *direntry) ...@@ -1997,7 +2002,7 @@ int cifs_rmdir(struct inode *inode, struct dentry *direntry)
current_time(inode); current_time(inode);
rmdir_exit: rmdir_exit:
kfree(full_path); free_dentry_path(page);
free_xid(xid); free_xid(xid);
return rc; return rc;
} }
...@@ -2072,8 +2077,8 @@ cifs_rename2(struct user_namespace *mnt_userns, struct inode *source_dir, ...@@ -2072,8 +2077,8 @@ cifs_rename2(struct user_namespace *mnt_userns, struct inode *source_dir,
struct dentry *source_dentry, struct inode *target_dir, struct dentry *source_dentry, struct inode *target_dir,
struct dentry *target_dentry, unsigned int flags) struct dentry *target_dentry, unsigned int flags)
{ {
const char *from_name = NULL; const char *from_name, *to_name;
const char *to_name = NULL; void *page1, *page2;
struct cifs_sb_info *cifs_sb; struct cifs_sb_info *cifs_sb;
struct tcon_link *tlink; struct tcon_link *tlink;
struct cifs_tcon *tcon; struct cifs_tcon *tcon;
...@@ -2091,21 +2096,19 @@ cifs_rename2(struct user_namespace *mnt_userns, struct inode *source_dir, ...@@ -2091,21 +2096,19 @@ cifs_rename2(struct user_namespace *mnt_userns, struct inode *source_dir,
return PTR_ERR(tlink); return PTR_ERR(tlink);
tcon = tlink_tcon(tlink); tcon = tlink_tcon(tlink);
page1 = alloc_dentry_path();
page2 = alloc_dentry_path();
xid = get_xid(); xid = get_xid();
/* from_name = build_path_from_dentry(source_dentry, page1);
* we already have the rename sem so we do not need to if (IS_ERR(from_name)) {
* grab it again here to protect the path integrity rc = PTR_ERR(from_name);
*/
from_name = build_path_from_dentry(source_dentry);
if (from_name == NULL) {
rc = -ENOMEM;
goto cifs_rename_exit; goto cifs_rename_exit;
} }
to_name = build_path_from_dentry(target_dentry); to_name = build_path_from_dentry(target_dentry, page2);
if (to_name == NULL) { if (IS_ERR(to_name)) {
rc = -ENOMEM; rc = PTR_ERR(to_name);
goto cifs_rename_exit; goto cifs_rename_exit;
} }
...@@ -2177,8 +2180,8 @@ cifs_rename2(struct user_namespace *mnt_userns, struct inode *source_dir, ...@@ -2177,8 +2180,8 @@ cifs_rename2(struct user_namespace *mnt_userns, struct inode *source_dir,
cifs_rename_exit: cifs_rename_exit:
kfree(info_buf_source); kfree(info_buf_source);
kfree(from_name); free_dentry_path(page2);
kfree(to_name); free_dentry_path(page1);
free_xid(xid); free_xid(xid);
cifs_put_tlink(tlink); cifs_put_tlink(tlink);
return rc; return rc;
...@@ -2317,7 +2320,8 @@ int cifs_revalidate_dentry_attr(struct dentry *dentry) ...@@ -2317,7 +2320,8 @@ int cifs_revalidate_dentry_attr(struct dentry *dentry)
int rc = 0; int rc = 0;
struct inode *inode = d_inode(dentry); struct inode *inode = d_inode(dentry);
struct super_block *sb = dentry->d_sb; struct super_block *sb = dentry->d_sb;
const char *full_path = NULL; const char *full_path;
void *page;
int count = 0; int count = 0;
if (inode == NULL) if (inode == NULL)
...@@ -2328,11 +2332,10 @@ int cifs_revalidate_dentry_attr(struct dentry *dentry) ...@@ -2328,11 +2332,10 @@ int cifs_revalidate_dentry_attr(struct dentry *dentry)
xid = get_xid(); xid = get_xid();
/* can not safely grab the rename sem here if rename calls revalidate page = alloc_dentry_path();
since that would deadlock */ full_path = build_path_from_dentry(dentry, page);
full_path = build_path_from_dentry(dentry); if (IS_ERR(full_path)) {
if (full_path == NULL) { rc = PTR_ERR(full_path);
rc = -ENOMEM;
goto out; goto out;
} }
...@@ -2351,7 +2354,7 @@ int cifs_revalidate_dentry_attr(struct dentry *dentry) ...@@ -2351,7 +2354,7 @@ int cifs_revalidate_dentry_attr(struct dentry *dentry)
if (rc == -EAGAIN && count++ < 10) if (rc == -EAGAIN && count++ < 10)
goto again; goto again;
out: out:
kfree(full_path); free_dentry_path(page);
free_xid(xid); free_xid(xid);
return rc; return rc;
...@@ -2613,7 +2616,8 @@ cifs_setattr_unix(struct dentry *direntry, struct iattr *attrs) ...@@ -2613,7 +2616,8 @@ cifs_setattr_unix(struct dentry *direntry, struct iattr *attrs)
{ {
int rc; int rc;
unsigned int xid; unsigned int xid;
const char *full_path = NULL; const char *full_path;
void *page = alloc_dentry_path();
struct inode *inode = d_inode(direntry); struct inode *inode = d_inode(direntry);
struct cifsInodeInfo *cifsInode = CIFS_I(inode); struct cifsInodeInfo *cifsInode = CIFS_I(inode);
struct cifs_sb_info *cifs_sb = CIFS_SB(inode->i_sb); struct cifs_sb_info *cifs_sb = CIFS_SB(inode->i_sb);
...@@ -2634,9 +2638,9 @@ cifs_setattr_unix(struct dentry *direntry, struct iattr *attrs) ...@@ -2634,9 +2638,9 @@ cifs_setattr_unix(struct dentry *direntry, struct iattr *attrs)
if (rc < 0) if (rc < 0)
goto out; goto out;
full_path = build_path_from_dentry(direntry); full_path = build_path_from_dentry(direntry, page);
if (full_path == NULL) { if (IS_ERR(full_path)) {
rc = -ENOMEM; rc = PTR_ERR(full_path);
goto out; goto out;
} }
...@@ -2748,7 +2752,7 @@ cifs_setattr_unix(struct dentry *direntry, struct iattr *attrs) ...@@ -2748,7 +2752,7 @@ cifs_setattr_unix(struct dentry *direntry, struct iattr *attrs)
cifsInode->time = 0; cifsInode->time = 0;
out: out:
kfree(args); kfree(args);
kfree(full_path); free_dentry_path(page);
free_xid(xid); free_xid(xid);
return rc; return rc;
} }
...@@ -2764,7 +2768,8 @@ cifs_setattr_nounix(struct dentry *direntry, struct iattr *attrs) ...@@ -2764,7 +2768,8 @@ cifs_setattr_nounix(struct dentry *direntry, struct iattr *attrs)
struct cifsInodeInfo *cifsInode = CIFS_I(inode); struct cifsInodeInfo *cifsInode = CIFS_I(inode);
struct cifsFileInfo *wfile; struct cifsFileInfo *wfile;
struct cifs_tcon *tcon; struct cifs_tcon *tcon;
const char *full_path = NULL; const char *full_path;
void *page = alloc_dentry_path();
int rc = -EACCES; int rc = -EACCES;
__u32 dosattr = 0; __u32 dosattr = 0;
__u64 mode = NO_CHANGE_64; __u64 mode = NO_CHANGE_64;
...@@ -2778,16 +2783,13 @@ cifs_setattr_nounix(struct dentry *direntry, struct iattr *attrs) ...@@ -2778,16 +2783,13 @@ cifs_setattr_nounix(struct dentry *direntry, struct iattr *attrs)
attrs->ia_valid |= ATTR_FORCE; attrs->ia_valid |= ATTR_FORCE;
rc = setattr_prepare(&init_user_ns, direntry, attrs); rc = setattr_prepare(&init_user_ns, direntry, attrs);
if (rc < 0) { if (rc < 0)
free_xid(xid); goto cifs_setattr_exit;
return rc;
}
full_path = build_path_from_dentry(direntry); full_path = build_path_from_dentry(direntry, page);
if (full_path == NULL) { if (IS_ERR(full_path)) {
rc = -ENOMEM; rc = PTR_ERR(full_path);
free_xid(xid); goto cifs_setattr_exit;
return rc;
} }
/* /*
...@@ -2937,8 +2939,8 @@ cifs_setattr_nounix(struct dentry *direntry, struct iattr *attrs) ...@@ -2937,8 +2939,8 @@ cifs_setattr_nounix(struct dentry *direntry, struct iattr *attrs)
mark_inode_dirty(inode); mark_inode_dirty(inode);
cifs_setattr_exit: cifs_setattr_exit:
kfree(full_path);
free_xid(xid); free_xid(xid);
free_dentry_path(page);
return rc; return rc;
} }
......
...@@ -43,12 +43,15 @@ static long cifs_ioctl_query_info(unsigned int xid, struct file *filep, ...@@ -43,12 +43,15 @@ static long cifs_ioctl_query_info(unsigned int xid, struct file *filep,
struct cifs_tcon *tcon = cifs_sb_master_tcon(cifs_sb); struct cifs_tcon *tcon = cifs_sb_master_tcon(cifs_sb);
struct dentry *dentry = filep->f_path.dentry; struct dentry *dentry = filep->f_path.dentry;
const unsigned char *path; const unsigned char *path;
void *page = alloc_dentry_path();
__le16 *utf16_path = NULL, root_path; __le16 *utf16_path = NULL, root_path;
int rc = 0; int rc = 0;
path = build_path_from_dentry(dentry); path = build_path_from_dentry(dentry, page);
if (path == NULL) if (IS_ERR(path)) {
return -ENOMEM; free_dentry_path(page);
return PTR_ERR(path);
}
cifs_dbg(FYI, "%s %s\n", __func__, path); cifs_dbg(FYI, "%s %s\n", __func__, path);
...@@ -73,7 +76,7 @@ static long cifs_ioctl_query_info(unsigned int xid, struct file *filep, ...@@ -73,7 +76,7 @@ static long cifs_ioctl_query_info(unsigned int xid, struct file *filep,
ici_exit: ici_exit:
if (utf16_path != &root_path) if (utf16_path != &root_path)
kfree(utf16_path); kfree(utf16_path);
kfree(path); free_dentry_path(page);
return rc; return rc;
} }
......
...@@ -510,8 +510,8 @@ cifs_hardlink(struct dentry *old_file, struct inode *inode, ...@@ -510,8 +510,8 @@ cifs_hardlink(struct dentry *old_file, struct inode *inode,
{ {
int rc = -EACCES; int rc = -EACCES;
unsigned int xid; unsigned int xid;
const char *from_name = NULL; const char *from_name, *to_name;
const char *to_name = NULL; void *page1, *page2;
struct cifs_sb_info *cifs_sb = CIFS_SB(inode->i_sb); struct cifs_sb_info *cifs_sb = CIFS_SB(inode->i_sb);
struct tcon_link *tlink; struct tcon_link *tlink;
struct cifs_tcon *tcon; struct cifs_tcon *tcon;
...@@ -524,11 +524,17 @@ cifs_hardlink(struct dentry *old_file, struct inode *inode, ...@@ -524,11 +524,17 @@ cifs_hardlink(struct dentry *old_file, struct inode *inode,
tcon = tlink_tcon(tlink); tcon = tlink_tcon(tlink);
xid = get_xid(); xid = get_xid();
page1 = alloc_dentry_path();
page2 = alloc_dentry_path();
from_name = build_path_from_dentry(old_file); from_name = build_path_from_dentry(old_file, page1);
to_name = build_path_from_dentry(direntry); if (IS_ERR(from_name)) {
if ((from_name == NULL) || (to_name == NULL)) { rc = PTR_ERR(from_name);
rc = -ENOMEM; goto cifs_hl_exit;
}
to_name = build_path_from_dentry(direntry, page2);
if (IS_ERR(to_name)) {
rc = PTR_ERR(to_name);
goto cifs_hl_exit; goto cifs_hl_exit;
} }
...@@ -587,8 +593,8 @@ cifs_hardlink(struct dentry *old_file, struct inode *inode, ...@@ -587,8 +593,8 @@ cifs_hardlink(struct dentry *old_file, struct inode *inode,
} }
cifs_hl_exit: cifs_hl_exit:
kfree(from_name); free_dentry_path(page1);
kfree(to_name); free_dentry_path(page2);
free_xid(xid); free_xid(xid);
cifs_put_tlink(tlink); cifs_put_tlink(tlink);
return rc; return rc;
...@@ -600,7 +606,8 @@ cifs_get_link(struct dentry *direntry, struct inode *inode, ...@@ -600,7 +606,8 @@ cifs_get_link(struct dentry *direntry, struct inode *inode,
{ {
int rc = -ENOMEM; int rc = -ENOMEM;
unsigned int xid; unsigned int xid;
const char *full_path = NULL; const char *full_path;
void *page;
char *target_path = NULL; char *target_path = NULL;
struct cifs_sb_info *cifs_sb = CIFS_SB(inode->i_sb); struct cifs_sb_info *cifs_sb = CIFS_SB(inode->i_sb);
struct tcon_link *tlink = NULL; struct tcon_link *tlink = NULL;
...@@ -620,11 +627,13 @@ cifs_get_link(struct dentry *direntry, struct inode *inode, ...@@ -620,11 +627,13 @@ cifs_get_link(struct dentry *direntry, struct inode *inode,
tcon = tlink_tcon(tlink); tcon = tlink_tcon(tlink);
server = tcon->ses->server; server = tcon->ses->server;
full_path = build_path_from_dentry(direntry); page = alloc_dentry_path();
if (!full_path) { full_path = build_path_from_dentry(direntry, page);
if (IS_ERR(full_path)) {
free_xid(xid); free_xid(xid);
cifs_put_tlink(tlink); cifs_put_tlink(tlink);
return ERR_PTR(-ENOMEM); free_dentry_path(page);
return ERR_CAST(full_path);
} }
cifs_dbg(FYI, "Full path: %s inode = 0x%p\n", full_path, inode); cifs_dbg(FYI, "Full path: %s inode = 0x%p\n", full_path, inode);
...@@ -649,7 +658,7 @@ cifs_get_link(struct dentry *direntry, struct inode *inode, ...@@ -649,7 +658,7 @@ cifs_get_link(struct dentry *direntry, struct inode *inode,
&target_path, reparse_point); &target_path, reparse_point);
} }
kfree(full_path); free_dentry_path(page);
free_xid(xid); free_xid(xid);
cifs_put_tlink(tlink); cifs_put_tlink(tlink);
if (rc != 0) { if (rc != 0) {
...@@ -669,7 +678,8 @@ cifs_symlink(struct user_namespace *mnt_userns, struct inode *inode, ...@@ -669,7 +678,8 @@ cifs_symlink(struct user_namespace *mnt_userns, struct inode *inode,
struct cifs_sb_info *cifs_sb = CIFS_SB(inode->i_sb); struct cifs_sb_info *cifs_sb = CIFS_SB(inode->i_sb);
struct tcon_link *tlink; struct tcon_link *tlink;
struct cifs_tcon *pTcon; struct cifs_tcon *pTcon;
const char *full_path = NULL; const char *full_path;
void *page = alloc_dentry_path();
struct inode *newinode = NULL; struct inode *newinode = NULL;
xid = get_xid(); xid = get_xid();
...@@ -681,9 +691,9 @@ cifs_symlink(struct user_namespace *mnt_userns, struct inode *inode, ...@@ -681,9 +691,9 @@ cifs_symlink(struct user_namespace *mnt_userns, struct inode *inode,
} }
pTcon = tlink_tcon(tlink); pTcon = tlink_tcon(tlink);
full_path = build_path_from_dentry(direntry); full_path = build_path_from_dentry(direntry, page);
if (full_path == NULL) { if (IS_ERR(full_path)) {
rc = -ENOMEM; rc = PTR_ERR(full_path);
goto symlink_exit; goto symlink_exit;
} }
...@@ -719,7 +729,7 @@ cifs_symlink(struct user_namespace *mnt_userns, struct inode *inode, ...@@ -719,7 +729,7 @@ cifs_symlink(struct user_namespace *mnt_userns, struct inode *inode,
} }
} }
symlink_exit: symlink_exit:
kfree(full_path); free_dentry_path(page);
cifs_put_tlink(tlink); cifs_put_tlink(tlink);
free_xid(xid); free_xid(xid);
return rc; return rc;
......
...@@ -942,13 +942,14 @@ int cifs_readdir(struct file *file, struct dir_context *ctx) ...@@ -942,13 +942,14 @@ int cifs_readdir(struct file *file, struct dir_context *ctx)
char *tmp_buf = NULL; char *tmp_buf = NULL;
char *end_of_smb; char *end_of_smb;
unsigned int max_len; unsigned int max_len;
const char *full_path = NULL; const char *full_path;
void *page = alloc_dentry_path();
xid = get_xid(); xid = get_xid();
full_path = build_path_from_dentry(file_dentry(file)); full_path = build_path_from_dentry(file_dentry(file), page);
if (full_path == NULL) { if (IS_ERR(full_path)) {
rc = -ENOMEM; rc = PTR_ERR(full_path);
goto rddir2_exit; goto rddir2_exit;
} }
...@@ -1043,7 +1044,7 @@ int cifs_readdir(struct file *file, struct dir_context *ctx) ...@@ -1043,7 +1044,7 @@ int cifs_readdir(struct file *file, struct dir_context *ctx)
kfree(tmp_buf); kfree(tmp_buf);
rddir2_exit: rddir2_exit:
kfree(full_path); free_dentry_path(page);
free_xid(xid); free_xid(xid);
return rc; return rc;
} }
...@@ -2217,20 +2217,21 @@ smb3_notify(const unsigned int xid, struct file *pfile, ...@@ -2217,20 +2217,21 @@ smb3_notify(const unsigned int xid, struct file *pfile,
struct smb3_notify notify; struct smb3_notify notify;
struct dentry *dentry = pfile->f_path.dentry; struct dentry *dentry = pfile->f_path.dentry;
struct inode *inode = file_inode(pfile); struct inode *inode = file_inode(pfile);
struct cifs_sb_info *cifs_sb; struct cifs_sb_info *cifs_sb = CIFS_SB(inode->i_sb);
struct cifs_open_parms oparms; struct cifs_open_parms oparms;
struct cifs_fid fid; struct cifs_fid fid;
struct cifs_tcon *tcon; struct cifs_tcon *tcon;
const unsigned char *path = NULL; const unsigned char *path;
void *page = alloc_dentry_path();
__le16 *utf16_path = NULL; __le16 *utf16_path = NULL;
u8 oplock = SMB2_OPLOCK_LEVEL_NONE; u8 oplock = SMB2_OPLOCK_LEVEL_NONE;
int rc = 0; int rc = 0;
path = build_path_from_dentry(dentry); path = build_path_from_dentry(dentry, page);
if (path == NULL) if (IS_ERR(path)) {
return -ENOMEM; rc = PTR_ERR(path);
goto notify_exit;
cifs_sb = CIFS_SB(inode->i_sb); }
utf16_path = cifs_convert_path_to_utf16(path + 1, cifs_sb); utf16_path = cifs_convert_path_to_utf16(path + 1, cifs_sb);
if (utf16_path == NULL) { if (utf16_path == NULL) {
...@@ -2264,7 +2265,7 @@ smb3_notify(const unsigned int xid, struct file *pfile, ...@@ -2264,7 +2265,7 @@ smb3_notify(const unsigned int xid, struct file *pfile,
cifs_dbg(FYI, "change notify for path %s rc %d\n", path, rc); cifs_dbg(FYI, "change notify for path %s rc %d\n", path, rc);
notify_exit: notify_exit:
kfree(path); free_dentry_path(page);
kfree(utf16_path); kfree(utf16_path);
return rc; return rc;
} }
......
...@@ -113,6 +113,7 @@ static int cifs_xattr_set(const struct xattr_handler *handler, ...@@ -113,6 +113,7 @@ static int cifs_xattr_set(const struct xattr_handler *handler,
struct tcon_link *tlink; struct tcon_link *tlink;
struct cifs_tcon *pTcon; struct cifs_tcon *pTcon;
const char *full_path; const char *full_path;
void *page;
tlink = cifs_sb_tlink(cifs_sb); tlink = cifs_sb_tlink(cifs_sb);
if (IS_ERR(tlink)) if (IS_ERR(tlink))
...@@ -120,10 +121,11 @@ static int cifs_xattr_set(const struct xattr_handler *handler, ...@@ -120,10 +121,11 @@ static int cifs_xattr_set(const struct xattr_handler *handler,
pTcon = tlink_tcon(tlink); pTcon = tlink_tcon(tlink);
xid = get_xid(); xid = get_xid();
page = alloc_dentry_path();
full_path = build_path_from_dentry(dentry); full_path = build_path_from_dentry(dentry, page);
if (full_path == NULL) { if (IS_ERR(full_path)) {
rc = -ENOMEM; rc = PTR_ERR(full_path);
goto out; goto out;
} }
/* return dos attributes as pseudo xattr */ /* return dos attributes as pseudo xattr */
...@@ -235,7 +237,7 @@ static int cifs_xattr_set(const struct xattr_handler *handler, ...@@ -235,7 +237,7 @@ static int cifs_xattr_set(const struct xattr_handler *handler,
} }
out: out:
kfree(full_path); free_dentry_path(page);
free_xid(xid); free_xid(xid);
cifs_put_tlink(tlink); cifs_put_tlink(tlink);
return rc; return rc;
...@@ -298,6 +300,7 @@ static int cifs_xattr_get(const struct xattr_handler *handler, ...@@ -298,6 +300,7 @@ static int cifs_xattr_get(const struct xattr_handler *handler,
struct tcon_link *tlink; struct tcon_link *tlink;
struct cifs_tcon *pTcon; struct cifs_tcon *pTcon;
const char *full_path; const char *full_path;
void *page;
tlink = cifs_sb_tlink(cifs_sb); tlink = cifs_sb_tlink(cifs_sb);
if (IS_ERR(tlink)) if (IS_ERR(tlink))
...@@ -305,10 +308,11 @@ static int cifs_xattr_get(const struct xattr_handler *handler, ...@@ -305,10 +308,11 @@ static int cifs_xattr_get(const struct xattr_handler *handler,
pTcon = tlink_tcon(tlink); pTcon = tlink_tcon(tlink);
xid = get_xid(); xid = get_xid();
page = alloc_dentry_path();
full_path = build_path_from_dentry(dentry); full_path = build_path_from_dentry(dentry, page);
if (full_path == NULL) { if (IS_ERR(full_path)) {
rc = -ENOMEM; rc = PTR_ERR(full_path);
goto out; goto out;
} }
...@@ -401,7 +405,7 @@ static int cifs_xattr_get(const struct xattr_handler *handler, ...@@ -401,7 +405,7 @@ static int cifs_xattr_get(const struct xattr_handler *handler,
rc = -EOPNOTSUPP; rc = -EOPNOTSUPP;
out: out:
kfree(full_path); free_dentry_path(page);
free_xid(xid); free_xid(xid);
cifs_put_tlink(tlink); cifs_put_tlink(tlink);
return rc; return rc;
...@@ -415,6 +419,7 @@ ssize_t cifs_listxattr(struct dentry *direntry, char *data, size_t buf_size) ...@@ -415,6 +419,7 @@ ssize_t cifs_listxattr(struct dentry *direntry, char *data, size_t buf_size)
struct tcon_link *tlink; struct tcon_link *tlink;
struct cifs_tcon *pTcon; struct cifs_tcon *pTcon;
const char *full_path; const char *full_path;
void *page;
if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_NO_XATTR) if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_NO_XATTR)
return -EOPNOTSUPP; return -EOPNOTSUPP;
...@@ -425,10 +430,11 @@ ssize_t cifs_listxattr(struct dentry *direntry, char *data, size_t buf_size) ...@@ -425,10 +430,11 @@ ssize_t cifs_listxattr(struct dentry *direntry, char *data, size_t buf_size)
pTcon = tlink_tcon(tlink); pTcon = tlink_tcon(tlink);
xid = get_xid(); xid = get_xid();
page = alloc_dentry_path();
full_path = build_path_from_dentry(direntry); full_path = build_path_from_dentry(direntry, page);
if (full_path == NULL) { if (IS_ERR(full_path)) {
rc = -ENOMEM; rc = PTR_ERR(full_path);
goto list_ea_exit; goto list_ea_exit;
} }
/* return dos attributes as pseudo xattr */ /* return dos attributes as pseudo xattr */
...@@ -442,7 +448,7 @@ ssize_t cifs_listxattr(struct dentry *direntry, char *data, size_t buf_size) ...@@ -442,7 +448,7 @@ ssize_t cifs_listxattr(struct dentry *direntry, char *data, size_t buf_size)
rc = pTcon->ses->server->ops->query_all_EAs(xid, pTcon, rc = pTcon->ses->server->ops->query_all_EAs(xid, pTcon,
full_path, NULL, data, buf_size, cifs_sb); full_path, NULL, data, buf_size, cifs_sb);
list_ea_exit: list_ea_exit:
kfree(full_path); free_dentry_path(page);
free_xid(xid); free_xid(xid);
cifs_put_tlink(tlink); cifs_put_tlink(tlink);
return rc; return rc;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment