Skip to content

Commit cf556ed

Browse files
committed
Merge tag 'ceph-for-5.6-rc2' of https://github.com/ceph/ceph-client
Pull ceph fixes from Ilya Dryomov: - make O_DIRECT | O_APPEND combination work better - redo the server path canonicalization patch that went into -rc1 - fix the 'noacl' mount option that got broken by the conversion to the new mount API in 5.5 * tag 'ceph-for-5.6-rc2' of https://github.com/ceph/ceph-client: ceph: noacl mount option is effectively ignored ceph: canonicalize server path in place ceph: do not execute direct write in parallel if O_APPEND is specified
2 parents ca60ad6 + 3b20bc2 commit cf556ed

File tree

3 files changed

+44
-104
lines changed

3 files changed

+44
-104
lines changed

fs/ceph/file.c

Lines changed: 11 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1418,6 +1418,7 @@ static ssize_t ceph_write_iter(struct kiocb *iocb, struct iov_iter *from)
14181418
struct ceph_cap_flush *prealloc_cf;
14191419
ssize_t count, written = 0;
14201420
int err, want, got;
1421+
bool direct_lock = false;
14211422
loff_t pos;
14221423
loff_t limit = max(i_size_read(inode), fsc->max_file_size);
14231424

@@ -1428,8 +1429,11 @@ static ssize_t ceph_write_iter(struct kiocb *iocb, struct iov_iter *from)
14281429
if (!prealloc_cf)
14291430
return -ENOMEM;
14301431

1432+
if ((iocb->ki_flags & (IOCB_DIRECT | IOCB_APPEND)) == IOCB_DIRECT)
1433+
direct_lock = true;
1434+
14311435
retry_snap:
1432-
if (iocb->ki_flags & IOCB_DIRECT)
1436+
if (direct_lock)
14331437
ceph_start_io_direct(inode);
14341438
else
14351439
ceph_start_io_write(inode);
@@ -1519,14 +1523,15 @@ static ssize_t ceph_write_iter(struct kiocb *iocb, struct iov_iter *from)
15191523

15201524
/* we might need to revert back to that point */
15211525
data = *from;
1522-
if (iocb->ki_flags & IOCB_DIRECT) {
1526+
if (iocb->ki_flags & IOCB_DIRECT)
15231527
written = ceph_direct_read_write(iocb, &data, snapc,
15241528
&prealloc_cf);
1525-
ceph_end_io_direct(inode);
1526-
} else {
1529+
else
15271530
written = ceph_sync_write(iocb, &data, pos, snapc);
1531+
if (direct_lock)
1532+
ceph_end_io_direct(inode);
1533+
else
15281534
ceph_end_io_write(inode);
1529-
}
15301535
if (written > 0)
15311536
iov_iter_advance(from, written);
15321537
ceph_put_snap_context(snapc);
@@ -1577,7 +1582,7 @@ static ssize_t ceph_write_iter(struct kiocb *iocb, struct iov_iter *from)
15771582

15781583
goto out_unlocked;
15791584
out:
1580-
if (iocb->ki_flags & IOCB_DIRECT)
1585+
if (direct_lock)
15811586
ceph_end_io_direct(inode);
15821587
else
15831588
ceph_end_io_write(inode);

fs/ceph/super.c

Lines changed: 32 additions & 97 deletions
Original file line numberDiff line numberDiff line change
@@ -202,6 +202,26 @@ struct ceph_parse_opts_ctx {
202202
struct ceph_mount_options *opts;
203203
};
204204

205+
/*
206+
* Remove adjacent slashes and then the trailing slash, unless it is
207+
* the only remaining character.
208+
*
209+
* E.g. "//dir1////dir2///" --> "/dir1/dir2", "///" --> "/".
210+
*/
211+
static void canonicalize_path(char *path)
212+
{
213+
int i, j = 0;
214+
215+
for (i = 0; path[i] != '\0'; i++) {
216+
if (path[i] != '/' || j < 1 || path[j - 1] != '/')
217+
path[j++] = path[i];
218+
}
219+
220+
if (j > 1 && path[j - 1] == '/')
221+
j--;
222+
path[j] = '\0';
223+
}
224+
205225
/*
206226
* Parse the source parameter. Distinguish the server list from the path.
207227
*
@@ -224,15 +244,16 @@ static int ceph_parse_source(struct fs_parameter *param, struct fs_context *fc)
224244

225245
dev_name_end = strchr(dev_name, '/');
226246
if (dev_name_end) {
227-
kfree(fsopt->server_path);
228-
229247
/*
230248
* The server_path will include the whole chars from userland
231249
* including the leading '/'.
232250
*/
251+
kfree(fsopt->server_path);
233252
fsopt->server_path = kstrdup(dev_name_end, GFP_KERNEL);
234253
if (!fsopt->server_path)
235254
return -ENOMEM;
255+
256+
canonicalize_path(fsopt->server_path);
236257
} else {
237258
dev_name_end = dev_name + strlen(dev_name);
238259
}
@@ -456,81 +477,13 @@ static int strcmp_null(const char *s1, const char *s2)
456477
return strcmp(s1, s2);
457478
}
458479

459-
/**
460-
* path_remove_extra_slash - Remove the extra slashes in the server path
461-
* @server_path: the server path and could be NULL
462-
*
463-
* Return NULL if the path is NULL or only consists of "/", or a string
464-
* without any extra slashes including the leading slash(es) and the
465-
* slash(es) at the end of the server path, such as:
466-
* "//dir1////dir2///" --> "dir1/dir2"
467-
*/
468-
static char *path_remove_extra_slash(const char *server_path)
469-
{
470-
const char *path = server_path;
471-
const char *cur, *end;
472-
char *buf, *p;
473-
int len;
474-
475-
/* if the server path is omitted */
476-
if (!path)
477-
return NULL;
478-
479-
/* remove all the leading slashes */
480-
while (*path == '/')
481-
path++;
482-
483-
/* if the server path only consists of slashes */
484-
if (*path == '\0')
485-
return NULL;
486-
487-
len = strlen(path);
488-
489-
buf = kmalloc(len + 1, GFP_KERNEL);
490-
if (!buf)
491-
return ERR_PTR(-ENOMEM);
492-
493-
end = path + len;
494-
p = buf;
495-
do {
496-
cur = strchr(path, '/');
497-
if (!cur)
498-
cur = end;
499-
500-
len = cur - path;
501-
502-
/* including one '/' */
503-
if (cur != end)
504-
len += 1;
505-
506-
memcpy(p, path, len);
507-
p += len;
508-
509-
while (cur <= end && *cur == '/')
510-
cur++;
511-
path = cur;
512-
} while (path < end);
513-
514-
*p = '\0';
515-
516-
/*
517-
* remove the last slash if there has and just to make sure that
518-
* we will get something like "dir1/dir2"
519-
*/
520-
if (*(--p) == '/')
521-
*p = '\0';
522-
523-
return buf;
524-
}
525-
526480
static int compare_mount_options(struct ceph_mount_options *new_fsopt,
527481
struct ceph_options *new_opt,
528482
struct ceph_fs_client *fsc)
529483
{
530484
struct ceph_mount_options *fsopt1 = new_fsopt;
531485
struct ceph_mount_options *fsopt2 = fsc->mount_options;
532486
int ofs = offsetof(struct ceph_mount_options, snapdir_name);
533-
char *p1, *p2;
534487
int ret;
535488

536489
ret = memcmp(fsopt1, fsopt2, ofs);
@@ -540,21 +493,12 @@ static int compare_mount_options(struct ceph_mount_options *new_fsopt,
540493
ret = strcmp_null(fsopt1->snapdir_name, fsopt2->snapdir_name);
541494
if (ret)
542495
return ret;
496+
543497
ret = strcmp_null(fsopt1->mds_namespace, fsopt2->mds_namespace);
544498
if (ret)
545499
return ret;
546500

547-
p1 = path_remove_extra_slash(fsopt1->server_path);
548-
if (IS_ERR(p1))
549-
return PTR_ERR(p1);
550-
p2 = path_remove_extra_slash(fsopt2->server_path);
551-
if (IS_ERR(p2)) {
552-
kfree(p1);
553-
return PTR_ERR(p2);
554-
}
555-
ret = strcmp_null(p1, p2);
556-
kfree(p1);
557-
kfree(p2);
501+
ret = strcmp_null(fsopt1->server_path, fsopt2->server_path);
558502
if (ret)
559503
return ret;
560504

@@ -957,7 +901,9 @@ static struct dentry *ceph_real_mount(struct ceph_fs_client *fsc,
957901
mutex_lock(&fsc->client->mount_mutex);
958902

959903
if (!fsc->sb->s_root) {
960-
const char *path, *p;
904+
const char *path = fsc->mount_options->server_path ?
905+
fsc->mount_options->server_path + 1 : "";
906+
961907
err = __ceph_open_session(fsc->client, started);
962908
if (err < 0)
963909
goto out;
@@ -969,22 +915,11 @@ static struct dentry *ceph_real_mount(struct ceph_fs_client *fsc,
969915
goto out;
970916
}
971917

972-
p = path_remove_extra_slash(fsc->mount_options->server_path);
973-
if (IS_ERR(p)) {
974-
err = PTR_ERR(p);
975-
goto out;
976-
}
977-
/* if the server path is omitted or just consists of '/' */
978-
if (!p)
979-
path = "";
980-
else
981-
path = p;
982918
dout("mount opening path '%s'\n", path);
983919

984920
ceph_fs_debugfs_init(fsc);
985921

986922
root = open_root_dentry(fsc, path, started);
987-
kfree(p);
988923
if (IS_ERR(root)) {
989924
err = PTR_ERR(root);
990925
goto out;
@@ -1097,10 +1032,6 @@ static int ceph_get_tree(struct fs_context *fc)
10971032
if (!fc->source)
10981033
return invalfc(fc, "No source");
10991034

1100-
#ifdef CONFIG_CEPH_FS_POSIX_ACL
1101-
fc->sb_flags |= SB_POSIXACL;
1102-
#endif
1103-
11041035
/* create client (which we may/may not use) */
11051036
fsc = create_fs_client(pctx->opts, pctx->copts);
11061037
pctx->opts = NULL;
@@ -1223,6 +1154,10 @@ static int ceph_init_fs_context(struct fs_context *fc)
12231154
fsopt->max_readdir_bytes = CEPH_MAX_READDIR_BYTES_DEFAULT;
12241155
fsopt->congestion_kb = default_congestion_kb();
12251156

1157+
#ifdef CONFIG_CEPH_FS_POSIX_ACL
1158+
fc->sb_flags |= SB_POSIXACL;
1159+
#endif
1160+
12261161
fc->fs_private = pctx;
12271162
fc->ops = &ceph_context_ops;
12281163
return 0;

fs/ceph/super.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -91,7 +91,7 @@ struct ceph_mount_options {
9191

9292
char *snapdir_name; /* default ".snap" */
9393
char *mds_namespace; /* default NULL */
94-
char *server_path; /* default "/" */
94+
char *server_path; /* default NULL (means "/") */
9595
char *fscache_uniq; /* default NULL */
9696
};
9797

0 commit comments

Comments
 (0)