Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

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

+44 -104
+11 -6
fs/ceph/file.c
··· 1418 1418 struct ceph_cap_flush *prealloc_cf; 1419 1419 ssize_t count, written = 0; 1420 1420 int err, want, got; 1421 + bool direct_lock = false; 1421 1422 loff_t pos; 1422 1423 loff_t limit = max(i_size_read(inode), fsc->max_file_size); 1423 1424 ··· 1429 1428 if (!prealloc_cf) 1430 1429 return -ENOMEM; 1431 1430 1431 + if ((iocb->ki_flags & (IOCB_DIRECT | IOCB_APPEND)) == IOCB_DIRECT) 1432 + direct_lock = true; 1433 + 1432 1434 retry_snap: 1433 - if (iocb->ki_flags & IOCB_DIRECT) 1435 + if (direct_lock) 1434 1436 ceph_start_io_direct(inode); 1435 1437 else 1436 1438 ceph_start_io_write(inode); ··· 1523 1519 1524 1520 /* we might need to revert back to that point */ 1525 1521 data = *from; 1526 - if (iocb->ki_flags & IOCB_DIRECT) { 1522 + if (iocb->ki_flags & IOCB_DIRECT) 1527 1523 written = ceph_direct_read_write(iocb, &data, snapc, 1528 1524 &prealloc_cf); 1529 - ceph_end_io_direct(inode); 1530 - } else { 1525 + else 1531 1526 written = ceph_sync_write(iocb, &data, pos, snapc); 1527 + if (direct_lock) 1528 + ceph_end_io_direct(inode); 1529 + else 1532 1530 ceph_end_io_write(inode); 1533 - } 1534 1531 if (written > 0) 1535 1532 iov_iter_advance(from, written); 1536 1533 ceph_put_snap_context(snapc); ··· 1582 1577 1583 1578 goto out_unlocked; 1584 1579 out: 1585 - if (iocb->ki_flags & IOCB_DIRECT) 1580 + if (direct_lock) 1586 1581 ceph_end_io_direct(inode); 1587 1582 else 1588 1583 ceph_end_io_write(inode);
+32 -97
fs/ceph/super.c
··· 203 203 }; 204 204 205 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 + 225 + /* 206 226 * Parse the source parameter. Distinguish the server list from the path. 207 227 * 208 228 * The source will look like: ··· 244 224 245 225 dev_name_end = strchr(dev_name, '/'); 246 226 if (dev_name_end) { 247 - kfree(fsopt->server_path); 248 - 249 227 /* 250 228 * The server_path will include the whole chars from userland 251 229 * including the leading '/'. 252 230 */ 231 + kfree(fsopt->server_path); 253 232 fsopt->server_path = kstrdup(dev_name_end, GFP_KERNEL); 254 233 if (!fsopt->server_path) 255 234 return -ENOMEM; 235 + 236 + canonicalize_path(fsopt->server_path); 256 237 } else { 257 238 dev_name_end = dev_name + strlen(dev_name); 258 239 } ··· 477 456 return strcmp(s1, s2); 478 457 } 479 458 480 - /** 481 - * path_remove_extra_slash - Remove the extra slashes in the server path 482 - * @server_path: the server path and could be NULL 483 - * 484 - * Return NULL if the path is NULL or only consists of "/", or a string 485 - * without any extra slashes including the leading slash(es) and the 486 - * slash(es) at the end of the server path, such as: 487 - * "//dir1////dir2///" --> "dir1/dir2" 488 - */ 489 - static char *path_remove_extra_slash(const char *server_path) 490 - { 491 - const char *path = server_path; 492 - const char *cur, *end; 493 - char *buf, *p; 494 - int len; 495 - 496 - /* if the server path is omitted */ 497 - if (!path) 498 - return NULL; 499 - 500 - /* remove all the leading slashes */ 501 - while (*path == '/') 502 - path++; 503 - 504 - /* if the server path only consists of slashes */ 505 - if (*path == '\0') 506 - return NULL; 507 - 508 - len = strlen(path); 509 - 510 - buf = kmalloc(len + 1, GFP_KERNEL); 511 - if (!buf) 512 - return ERR_PTR(-ENOMEM); 513 - 514 - end = path + len; 515 - p = buf; 516 - do { 517 - cur = strchr(path, '/'); 518 - if (!cur) 519 - cur = end; 520 - 521 - len = cur - path; 522 - 523 - /* including one '/' */ 524 - if (cur != end) 525 - len += 1; 526 - 527 - memcpy(p, path, len); 528 - p += len; 529 - 530 - while (cur <= end && *cur == '/') 531 - cur++; 532 - path = cur; 533 - } while (path < end); 534 - 535 - *p = '\0'; 536 - 537 - /* 538 - * remove the last slash if there has and just to make sure that 539 - * we will get something like "dir1/dir2" 540 - */ 541 - if (*(--p) == '/') 542 - *p = '\0'; 543 - 544 - return buf; 545 - } 546 - 547 459 static int compare_mount_options(struct ceph_mount_options *new_fsopt, 548 460 struct ceph_options *new_opt, 549 461 struct ceph_fs_client *fsc) ··· 484 530 struct ceph_mount_options *fsopt1 = new_fsopt; 485 531 struct ceph_mount_options *fsopt2 = fsc->mount_options; 486 532 int ofs = offsetof(struct ceph_mount_options, snapdir_name); 487 - char *p1, *p2; 488 533 int ret; 489 534 490 535 ret = memcmp(fsopt1, fsopt2, ofs); ··· 493 540 ret = strcmp_null(fsopt1->snapdir_name, fsopt2->snapdir_name); 494 541 if (ret) 495 542 return ret; 543 + 496 544 ret = strcmp_null(fsopt1->mds_namespace, fsopt2->mds_namespace); 497 545 if (ret) 498 546 return ret; 499 547 500 - p1 = path_remove_extra_slash(fsopt1->server_path); 501 - if (IS_ERR(p1)) 502 - return PTR_ERR(p1); 503 - p2 = path_remove_extra_slash(fsopt2->server_path); 504 - if (IS_ERR(p2)) { 505 - kfree(p1); 506 - return PTR_ERR(p2); 507 - } 508 - ret = strcmp_null(p1, p2); 509 - kfree(p1); 510 - kfree(p2); 548 + ret = strcmp_null(fsopt1->server_path, fsopt2->server_path); 511 549 if (ret) 512 550 return ret; 513 551 ··· 901 957 mutex_lock(&fsc->client->mount_mutex); 902 958 903 959 if (!fsc->sb->s_root) { 904 - const char *path, *p; 960 + const char *path = fsc->mount_options->server_path ? 961 + fsc->mount_options->server_path + 1 : ""; 962 + 905 963 err = __ceph_open_session(fsc->client, started); 906 964 if (err < 0) 907 965 goto out; ··· 915 969 goto out; 916 970 } 917 971 918 - p = path_remove_extra_slash(fsc->mount_options->server_path); 919 - if (IS_ERR(p)) { 920 - err = PTR_ERR(p); 921 - goto out; 922 - } 923 - /* if the server path is omitted or just consists of '/' */ 924 - if (!p) 925 - path = ""; 926 - else 927 - path = p; 928 972 dout("mount opening path '%s'\n", path); 929 973 930 974 ceph_fs_debugfs_init(fsc); 931 975 932 976 root = open_root_dentry(fsc, path, started); 933 - kfree(p); 934 977 if (IS_ERR(root)) { 935 978 err = PTR_ERR(root); 936 979 goto out; ··· 1031 1096 1032 1097 if (!fc->source) 1033 1098 return invalfc(fc, "No source"); 1034 - 1035 - #ifdef CONFIG_CEPH_FS_POSIX_ACL 1036 - fc->sb_flags |= SB_POSIXACL; 1037 - #endif 1038 1099 1039 1100 /* create client (which we may/may not use) */ 1040 1101 fsc = create_fs_client(pctx->opts, pctx->copts); ··· 1153 1222 fsopt->max_readdir = CEPH_MAX_READDIR_DEFAULT; 1154 1223 fsopt->max_readdir_bytes = CEPH_MAX_READDIR_BYTES_DEFAULT; 1155 1224 fsopt->congestion_kb = default_congestion_kb(); 1225 + 1226 + #ifdef CONFIG_CEPH_FS_POSIX_ACL 1227 + fc->sb_flags |= SB_POSIXACL; 1228 + #endif 1156 1229 1157 1230 fc->fs_private = pctx; 1158 1231 fc->ops = &ceph_context_ops;
+1 -1
fs/ceph/super.h
··· 91 91 92 92 char *snapdir_name; /* default ".snap" */ 93 93 char *mds_namespace; /* default NULL */ 94 - char *server_path; /* default "/" */ 94 + char *server_path; /* default NULL (means "/") */ 95 95 char *fscache_uniq; /* default NULL */ 96 96 }; 97 97