Skip to content

Commit a5dc90a

Browse files
neilbrownsmfrench
authored andcommitted
smb/server: simplify ksmbd_vfs_kern_path_locked()
ksmbd_vfs_kern_path_locked() first tries to look up the path with the given case. When this fails, if caseless is set, it loops over the components in the path, opening the relevant directory and searching for a name which matches. This name is copied over the original and the the process repeats. Each time a lookup with the newly updated path is repeated from the top (vfs_path_lookup()). When the last component has been case-corrected the simplest next step is to repeat the original lookup with ksmbd_vfs_path_lookup_locked(). If this works it gives exactly what we want, if it fails it gives the correct failure. This observation allows the code to be simplified, in particular removing the ksmbd_vfs_lock_parent() call. This patch also removes the duplication of name and filepath (two names for the one thing) and calls path_put(parent_path) sooner so parent_path can be passed directly to vfs_path_lookup avoiding the need to store it temporarily in path and then copying into parent_path. This patch removes one user of ksmbd_vfs_lock_parent() which will simplify a future patch. Signed-off-by: NeilBrown <[email protected]> Acked-by: Namjae Jeon <[email protected]> Signed-off-by: Steve French <[email protected]>
1 parent 09f124b commit a5dc90a

File tree

1 file changed

+42
-64
lines changed

1 file changed

+42
-64
lines changed

fs/smb/server/vfs.c

Lines changed: 42 additions & 64 deletions
Original file line numberDiff line numberDiff line change
@@ -1200,93 +1200,71 @@ static int ksmbd_vfs_lookup_in_dir(const struct path *dir, char *name,
12001200

12011201
/**
12021202
* ksmbd_vfs_kern_path_locked() - lookup a file and get path info
1203-
* @work: work
1204-
* @name: file path that is relative to share
1203+
* @work: work
1204+
* @filepath: file path that is relative to share
12051205
* @flags: lookup flags
12061206
* @parent_path: if lookup succeed, return parent_path info
12071207
* @path: if lookup succeed, return path info
12081208
* @caseless: caseless filename lookup
12091209
*
12101210
* Return: 0 on success, otherwise error
12111211
*/
1212-
int ksmbd_vfs_kern_path_locked(struct ksmbd_work *work, char *name,
1212+
int ksmbd_vfs_kern_path_locked(struct ksmbd_work *work, char *filepath,
12131213
unsigned int flags, struct path *parent_path,
12141214
struct path *path, bool caseless)
12151215
{
12161216
struct ksmbd_share_config *share_conf = work->tcon->share_conf;
1217+
size_t path_len, remain_len;
12171218
int err;
12181219

1219-
err = ksmbd_vfs_path_lookup_locked(share_conf, name, flags, parent_path,
1220+
retry:
1221+
err = ksmbd_vfs_path_lookup_locked(share_conf, filepath, flags, parent_path,
12201222
path);
1221-
if (!err)
1222-
return 0;
1223-
1224-
if (caseless) {
1225-
char *filepath;
1226-
size_t path_len, remain_len;
1227-
1228-
filepath = name;
1229-
path_len = strlen(filepath);
1230-
remain_len = path_len;
1231-
1232-
*parent_path = share_conf->vfs_path;
1233-
path_get(parent_path);
1234-
1235-
while (d_can_lookup(parent_path->dentry)) {
1236-
char *filename = filepath + path_len - remain_len;
1237-
char *next = strchrnul(filename, '/');
1238-
size_t filename_len = next - filename;
1239-
bool is_last = !next[0];
1240-
1241-
if (filename_len == 0)
1242-
break;
1223+
if (!err || !caseless)
1224+
return err;
12431225

1244-
err = ksmbd_vfs_lookup_in_dir(parent_path, filename,
1245-
filename_len,
1246-
work->conn->um);
1247-
if (err)
1248-
goto out2;
1226+
path_len = strlen(filepath);
1227+
remain_len = path_len;
12491228

1250-
next[0] = '\0';
1229+
*parent_path = share_conf->vfs_path;
1230+
path_get(parent_path);
12511231

1252-
err = vfs_path_lookup(share_conf->vfs_path.dentry,
1253-
share_conf->vfs_path.mnt,
1254-
filepath,
1255-
flags,
1256-
path);
1257-
if (!is_last)
1258-
next[0] = '/';
1259-
if (err)
1260-
goto out2;
1261-
else if (is_last)
1262-
goto out1;
1263-
path_put(parent_path);
1264-
*parent_path = *path;
1232+
while (d_can_lookup(parent_path->dentry)) {
1233+
char *filename = filepath + path_len - remain_len;
1234+
char *next = strchrnul(filename, '/');
1235+
size_t filename_len = next - filename;
1236+
bool is_last = !next[0];
12651237

1266-
remain_len -= filename_len + 1;
1267-
}
1238+
if (filename_len == 0)
1239+
break;
12681240

1269-
err = -EINVAL;
1270-
out2:
1241+
err = ksmbd_vfs_lookup_in_dir(parent_path, filename,
1242+
filename_len,
1243+
work->conn->um);
12711244
path_put(parent_path);
1272-
}
1273-
1274-
out1:
1275-
if (!err) {
1276-
err = mnt_want_write(parent_path->mnt);
1277-
if (err) {
1278-
path_put(path);
1279-
path_put(parent_path);
1280-
return err;
1245+
if (err)
1246+
goto out;
1247+
if (is_last) {
1248+
caseless = false;
1249+
goto retry;
12811250
}
1251+
next[0] = '\0';
1252+
1253+
err = vfs_path_lookup(share_conf->vfs_path.dentry,
1254+
share_conf->vfs_path.mnt,
1255+
filepath,
1256+
flags,
1257+
parent_path);
1258+
next[0] = '/';
1259+
if (err)
1260+
goto out;
12821261

1283-
err = ksmbd_vfs_lock_parent(parent_path->dentry, path->dentry);
1284-
if (err) {
1285-
mnt_drop_write(parent_path->mnt);
1286-
path_put(path);
1287-
path_put(parent_path);
1288-
}
1262+
remain_len -= filename_len + 1;
12891263
}
1264+
1265+
err = -EINVAL;
1266+
path_put(parent_path);
1267+
out:
12901268
return err;
12911269
}
12921270

0 commit comments

Comments
 (0)