Skip to content

Commit 6835398

Browse files
committed
Merge tag '5.6-smb3-fixes-and-dfs-and-readdir-improvements' of git://git.samba.org/sfrench/cifs-2.6
Pull cifs updates from Steve French: "Various SMB3/CIFS fixes including four for stable. - Improvement to fallocate (enables 3 additional xfstests) - Fix for file creation when mounting with modefromsid - Add ability to backup/restore dos attributes and creation time - DFS failover and reconnect fixes - performance optimization for readir Note that due to the upcoming SMB3 Test Event (at SNIA SDC next week) there will likely be more changesets near the end of the merge window (since we will be testing heavily next week, I held off on some patches and I expect some additional multichannel patches as well as patches to enable some additional xfstests)" * tag '5.6-smb3-fixes-and-dfs-and-readdir-improvements' of git://git.samba.org/sfrench/cifs-2.6: (24 commits) CIFS: Fix task struct use-after-free on reconnect cifs: use PTR_ERR_OR_ZERO() to simplify code cifs: add support for fallocate mode 0 for non-sparse files cifs: fix NULL dereference in match_prepath smb3: fix default permissions on new files when mounting with modefromsid CIFS: Add support for setting owner info, dos attributes, and create time cifs: remove set but not used variable 'server' cifs: Fix memory allocation in __smb2_handle_cancelled_cmd() cifs: Fix mount options set in automount cifs: fix unitialized variable poential problem with network I/O cache lock patch cifs: Fix return value in __update_cache_entry cifs: Avoid doing network I/O while holding cache lock cifs: Fix potential deadlock when updating vol in cifs_reconnect() cifs: Merge is_path_valid() into get_normalized_path() cifs: Introduce helpers for finding TCP connection cifs: Get rid of kstrdup_const()'d paths cifs: Clean up DFS referral cache cifs: Don't use iov_iter::type directly cifs: set correct max-buffer-size for smb2_ioctl_init() cifs: use compounding for open and first query-dir for readdir() ...
2 parents c899437 + f1f27ad commit 6835398

18 files changed

+1041
-713
lines changed

fs/cifs/cifs_dfs_ref.c

Lines changed: 43 additions & 54 deletions
Original file line numberDiff line numberDiff line change
@@ -120,17 +120,17 @@ cifs_build_devname(char *nodename, const char *prepath)
120120

121121

122122
/**
123-
* cifs_compose_mount_options - creates mount options for refferral
123+
* cifs_compose_mount_options - creates mount options for referral
124124
* @sb_mountdata: parent/root DFS mount options (template)
125125
* @fullpath: full path in UNC format
126-
* @ref: server's referral
126+
* @ref: optional server's referral
127127
* @devname: optional pointer for saving device name
128128
*
129129
* creates mount options for submount based on template options sb_mountdata
130130
* and replacing unc,ip,prefixpath options with ones we've got form ref_unc.
131131
*
132132
* Returns: pointer to new mount options or ERR_PTR.
133-
* Caller is responcible for freeing retunrned value if it is not error.
133+
* Caller is responsible for freeing returned value if it is not error.
134134
*/
135135
char *cifs_compose_mount_options(const char *sb_mountdata,
136136
const char *fullpath,
@@ -150,18 +150,27 @@ char *cifs_compose_mount_options(const char *sb_mountdata,
150150
if (sb_mountdata == NULL)
151151
return ERR_PTR(-EINVAL);
152152

153-
if (strlen(fullpath) - ref->path_consumed) {
154-
prepath = fullpath + ref->path_consumed;
155-
/* skip initial delimiter */
156-
if (*prepath == '/' || *prepath == '\\')
157-
prepath++;
158-
}
153+
if (ref) {
154+
if (strlen(fullpath) - ref->path_consumed) {
155+
prepath = fullpath + ref->path_consumed;
156+
/* skip initial delimiter */
157+
if (*prepath == '/' || *prepath == '\\')
158+
prepath++;
159+
}
159160

160-
name = cifs_build_devname(ref->node_name, prepath);
161-
if (IS_ERR(name)) {
162-
rc = PTR_ERR(name);
163-
name = NULL;
164-
goto compose_mount_options_err;
161+
name = cifs_build_devname(ref->node_name, prepath);
162+
if (IS_ERR(name)) {
163+
rc = PTR_ERR(name);
164+
name = NULL;
165+
goto compose_mount_options_err;
166+
}
167+
} else {
168+
name = cifs_build_devname((char *)fullpath, NULL);
169+
if (IS_ERR(name)) {
170+
rc = PTR_ERR(name);
171+
name = NULL;
172+
goto compose_mount_options_err;
173+
}
165174
}
166175

167176
rc = dns_resolve_server_name_to_ip(name, &srvIP);
@@ -225,6 +234,8 @@ char *cifs_compose_mount_options(const char *sb_mountdata,
225234

226235
if (devname)
227236
*devname = name;
237+
else
238+
kfree(name);
228239

229240
/*cifs_dbg(FYI, "%s: parent mountdata: %s\n", __func__, sb_mountdata);*/
230241
/*cifs_dbg(FYI, "%s: submount mountdata: %s\n", __func__, mountdata );*/
@@ -241,23 +252,23 @@ char *cifs_compose_mount_options(const char *sb_mountdata,
241252
}
242253

243254
/**
244-
* cifs_dfs_do_refmount - mounts specified path using provided refferal
255+
* cifs_dfs_do_mount - mounts specified path using DFS full path
256+
*
257+
* Always pass down @fullpath to smb3_do_mount() so we can use the root server
258+
* to perform failover in case we failed to connect to the first target in the
259+
* referral.
260+
*
245261
* @cifs_sb: parent/root superblock
246262
* @fullpath: full path in UNC format
247-
* @ref: server's referral
248263
*/
249-
static struct vfsmount *cifs_dfs_do_refmount(struct dentry *mntpt,
250-
struct cifs_sb_info *cifs_sb,
251-
const char *fullpath, const struct dfs_info3_param *ref)
264+
static struct vfsmount *cifs_dfs_do_mount(struct dentry *mntpt,
265+
struct cifs_sb_info *cifs_sb,
266+
const char *fullpath)
252267
{
253268
struct vfsmount *mnt;
254269
char *mountdata;
255270
char *devname;
256271

257-
/*
258-
* Always pass down the DFS full path to smb3_do_mount() so we
259-
* can use it later for failover.
260-
*/
261272
devname = kstrndup(fullpath, strlen(fullpath), GFP_KERNEL);
262273
if (!devname)
263274
return ERR_PTR(-ENOMEM);
@@ -266,7 +277,7 @@ static struct vfsmount *cifs_dfs_do_refmount(struct dentry *mntpt,
266277

267278
/* strip first '\' from fullpath */
268279
mountdata = cifs_compose_mount_options(cifs_sb->mountdata,
269-
fullpath + 1, ref, NULL);
280+
fullpath + 1, NULL, NULL);
270281
if (IS_ERR(mountdata)) {
271282
kfree(devname);
272283
return (struct vfsmount *)mountdata;
@@ -278,28 +289,16 @@ static struct vfsmount *cifs_dfs_do_refmount(struct dentry *mntpt,
278289
return mnt;
279290
}
280291

281-
static void dump_referral(const struct dfs_info3_param *ref)
282-
{
283-
cifs_dbg(FYI, "DFS: ref path: %s\n", ref->path_name);
284-
cifs_dbg(FYI, "DFS: node path: %s\n", ref->node_name);
285-
cifs_dbg(FYI, "DFS: fl: %d, srv_type: %d\n",
286-
ref->flags, ref->server_type);
287-
cifs_dbg(FYI, "DFS: ref_flags: %d, path_consumed: %d\n",
288-
ref->ref_flag, ref->path_consumed);
289-
}
290-
291292
/*
292293
* Create a vfsmount that we can automount
293294
*/
294295
static struct vfsmount *cifs_dfs_do_automount(struct dentry *mntpt)
295296
{
296-
struct dfs_info3_param referral = {0};
297297
struct cifs_sb_info *cifs_sb;
298298
struct cifs_ses *ses;
299299
struct cifs_tcon *tcon;
300300
char *full_path, *root_path;
301301
unsigned int xid;
302-
int len;
303302
int rc;
304303
struct vfsmount *mnt;
305304

@@ -357,7 +356,7 @@ static struct vfsmount *cifs_dfs_do_automount(struct dentry *mntpt)
357356
if (!rc) {
358357
rc = dfs_cache_find(xid, ses, cifs_sb->local_nls,
359358
cifs_remap(cifs_sb), full_path + 1,
360-
&referral, NULL);
359+
NULL, NULL);
361360
}
362361

363362
free_xid(xid);
@@ -366,26 +365,16 @@ static struct vfsmount *cifs_dfs_do_automount(struct dentry *mntpt)
366365
mnt = ERR_PTR(rc);
367366
goto free_root_path;
368367
}
369-
370-
dump_referral(&referral);
371-
372-
len = strlen(referral.node_name);
373-
if (len < 2) {
374-
cifs_dbg(VFS, "%s: Net Address path too short: %s\n",
375-
__func__, referral.node_name);
376-
mnt = ERR_PTR(-EINVAL);
377-
goto free_dfs_ref;
378-
}
379368
/*
380-
* cifs_mount() will retry every available node server in case
381-
* of failures.
369+
* OK - we were able to get and cache a referral for @full_path.
370+
*
371+
* Now, pass it down to cifs_mount() and it will retry every available
372+
* node server in case of failures - no need to do it here.
382373
*/
383-
mnt = cifs_dfs_do_refmount(mntpt, cifs_sb, full_path, &referral);
384-
cifs_dbg(FYI, "%s: cifs_dfs_do_refmount:%s , mnt:%p\n", __func__,
385-
referral.node_name, mnt);
374+
mnt = cifs_dfs_do_mount(mntpt, cifs_sb, full_path);
375+
cifs_dbg(FYI, "%s: cifs_dfs_do_mount:%s , mnt:%p\n", __func__,
376+
full_path + 1, mnt);
386377

387-
free_dfs_ref:
388-
free_dfs_info_param(&referral);
389378
free_root_path:
390379
kfree(root_path);
391380
free_full_path:

fs/cifs/cifsacl.c

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -802,6 +802,26 @@ static void parse_dacl(struct cifs_acl *pdacl, char *end_of_acl,
802802
return;
803803
}
804804

805+
unsigned int setup_authusers_ACE(struct cifs_ace *pntace)
806+
{
807+
int i;
808+
unsigned int ace_size = 20;
809+
810+
pntace->type = ACCESS_ALLOWED_ACE_TYPE;
811+
pntace->flags = 0x0;
812+
pntace->access_req = cpu_to_le32(GENERIC_ALL);
813+
pntace->sid.num_subauth = 1;
814+
pntace->sid.revision = 1;
815+
for (i = 0; i < NUM_AUTHS; i++)
816+
pntace->sid.authority[i] = sid_authusers.authority[i];
817+
818+
pntace->sid.sub_auth[0] = sid_authusers.sub_auth[0];
819+
820+
/* size = 1 + 1 + 2 + 4 + 1 + 1 + 6 + (psid->num_subauth*4) */
821+
pntace->size = cpu_to_le16(ace_size);
822+
return ace_size;
823+
}
824+
805825
/*
806826
* Fill in the special SID based on the mode. See
807827
* http://technet.microsoft.com/en-us/library/hh509017(v=ws.10).aspx

fs/cifs/cifsfs.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -149,6 +149,9 @@ extern ssize_t cifs_file_copychunk_range(unsigned int xid,
149149
size_t len, unsigned int flags);
150150

151151
extern long cifs_ioctl(struct file *filep, unsigned int cmd, unsigned long arg);
152+
extern void cifs_setsize(struct inode *inode, loff_t offset);
153+
extern int cifs_truncate_page(struct address_space *mapping, loff_t from);
154+
152155
#ifdef CONFIG_CIFS_NFSD_EXPORT
153156
extern const struct export_operations cifs_export_ops;
154157
#endif /* CONFIG_CIFS_NFSD_EXPORT */

fs/cifs/cifsglob.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1588,6 +1588,7 @@ struct mid_q_entry {
15881588
mid_callback_t *callback; /* call completion callback */
15891589
mid_handle_t *handle; /* call handle mid callback */
15901590
void *callback_data; /* general purpose pointer for callback */
1591+
struct task_struct *creator;
15911592
void *resp_buf; /* pointer to received SMB header */
15921593
unsigned int resp_buf_size;
15931594
int mid_state; /* wish this were enum but can not pass to wait_event */

fs/cifs/cifsproto.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -213,6 +213,7 @@ extern struct cifs_ntsd *get_cifs_acl_by_fid(struct cifs_sb_info *,
213213
const struct cifs_fid *, u32 *);
214214
extern int set_cifs_acl(struct cifs_ntsd *, __u32, struct inode *,
215215
const char *, int);
216+
extern unsigned int setup_authusers_ACE(struct cifs_ace *pace);
216217
extern unsigned int setup_special_mode_ACE(struct cifs_ace *pace, __u64 nmode);
217218

218219
extern void dequeue_mid(struct mid_q_entry *mid, bool malformed);
@@ -596,6 +597,9 @@ bool is_ses_using_iface(struct cifs_ses *ses, struct cifs_server_iface *iface);
596597

597598
void extract_unc_hostname(const char *unc, const char **h, size_t *len);
598599
int copy_path_name(char *dst, const char *src);
600+
int smb2_parse_query_directory(struct cifs_tcon *tcon, struct kvec *rsp_iov,
601+
int resp_buftype,
602+
struct cifs_search_info *srch_inf);
599603

600604
#ifdef CONFIG_CIFS_DFS_UPCALL
601605
static inline int get_dfs_path(const unsigned int xid, struct cifs_ses *ses,

fs/cifs/cifssmb.c

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4619,7 +4619,7 @@ CIFSFindFirst(const unsigned int xid, struct cifs_tcon *tcon,
46194619
psrch_inf->unicode = false;
46204620

46214621
psrch_inf->ntwrk_buf_start = (char *)pSMBr;
4622-
psrch_inf->smallBuf = 0;
4622+
psrch_inf->smallBuf = false;
46234623
psrch_inf->srch_entries_start =
46244624
(char *) &pSMBr->hdr.Protocol +
46254625
le16_to_cpu(pSMBr->t2.DataOffset);
@@ -4753,7 +4753,7 @@ int CIFSFindNext(const unsigned int xid, struct cifs_tcon *tcon,
47534753
cifs_buf_release(psrch_inf->ntwrk_buf_start);
47544754
psrch_inf->srch_entries_start = response_data;
47554755
psrch_inf->ntwrk_buf_start = (char *)pSMB;
4756-
psrch_inf->smallBuf = 0;
4756+
psrch_inf->smallBuf = false;
47574757
if (parms->EndofSearch)
47584758
psrch_inf->endOfSearch = true;
47594759
else

fs/cifs/connect.c

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3709,8 +3709,10 @@ match_prepath(struct super_block *sb, struct cifs_mnt_data *mnt_data)
37093709
{
37103710
struct cifs_sb_info *old = CIFS_SB(sb);
37113711
struct cifs_sb_info *new = mnt_data->cifs_sb;
3712-
bool old_set = old->mnt_cifs_flags & CIFS_MOUNT_USE_PREFIX_PATH;
3713-
bool new_set = new->mnt_cifs_flags & CIFS_MOUNT_USE_PREFIX_PATH;
3712+
bool old_set = (old->mnt_cifs_flags & CIFS_MOUNT_USE_PREFIX_PATH) &&
3713+
old->prepath;
3714+
bool new_set = (new->mnt_cifs_flags & CIFS_MOUNT_USE_PREFIX_PATH) &&
3715+
new->prepath;
37143716

37153717
if (old_set && new_set && !strcmp(new->prepath, old->prepath))
37163718
return 1;

0 commit comments

Comments
 (0)