From: Wang Shilong Date: Wed, 2 May 2018 08:54:15 +0000 (+0800) Subject: LU-10986 lfs: make lfs project tolerant errors X-Git-Tag: 2.11.53~21 X-Git-Url: https://git.whamcloud.com/?p=fs%2Flustre-release.git;a=commitdiff_plain;h=d189024bd3065c69c51ba90f6228c3ea28419dd0;hp=04585d02d1e175cb74254c58ee65291ff707a888 LU-10986 lfs: make lfs project tolerant errors This patch try to fix following problems: 1)command hang on pipe file, reproduced by following steps: $ mkfifo tmp/pipe $ lfs project -srp 500 tmp -->this will never finish. Problem is opening a pipe file will be blocked in default without O_NOBLOCK or O_NODELAY flag. 2)If a symbolic link with missing target exists, command returns error and does not process remaining entries. we should fix this problem by allowing command process further even it hit some errors. 3)fix a wrong check for MAX_PATH. Test-Parameters: trivial testlist=sanity-quota,sanity-quota Change-Id: I7d08a7547e6b1351a1eff23063da6cd9c4cdc5e3 Signed-off-by: Wang Shilong Reviewed-on: https://review.whamcloud.com/32243 Tested-by: Jenkins Tested-by: Maloo Reviewed-by: Andreas Dilger Reviewed-by: Yingjin Qian Reviewed-by: Oleg Drokin --- diff --git a/lustre/tests/sanity-quota.sh b/lustre/tests/sanity-quota.sh index ede0594..073a5af 100755 --- a/lustre/tests/sanity-quota.sh +++ b/lustre/tests/sanity-quota.sh @@ -3030,7 +3030,7 @@ test_55() { } run_test 55 "Chgrp should be affected by group quota" -test_56 () { +test_56() { setup_quota_test || error "setup quota failed with $?" set_ost_qtype $QTYPE || error "enable ost quota failed" @@ -3049,6 +3049,27 @@ test_56 () { } run_test 56 "lfs quota -t should work well" +test_57() { + setup_quota_test || error "setup quota failed with $?" + + local dir="$DIR/$tdir/dir" + mkdir -p $dir + mkfifo $dir/pipe + #try to change pipe file should not hang and return failure + wait_update_facet client "$LFS project -sp 1 $dir/pipe 2>&1 | + awk -F ':' '{ print \\\$2 }'" \ + " failed to get xattr for '$dir/pipe'" || return 1 + #command can process further if it hit some errors + touch $dir/aaa $dir/bbb + #create one invalid link file + ln -s $dir/not_exist_file $dir/ccc + local cnt=$(lfs project -r $dir 2>/dev/null | wc -l) + [ $cnt -eq 2 ] || error "expected 2 got $cnt" + + cleanup_quota_test +} +run_test 57 "lfs project could tolerate errors" + test_59() { if [ $(facet_fstype $SINGLEMDS) != ldiskfs ]; then skip "ldiskfs only test" diff --git a/lustre/utils/lfs_project.c b/lustre/utils/lfs_project.c index 180447a..07eff3c 100644 --- a/lustre/utils/lfs_project.c +++ b/lustre/utils/lfs_project.c @@ -79,7 +79,7 @@ static int project_get_xattr(const char *pathname, struct fsxattr *fsx) { int ret, fd; - fd = open(pathname, O_RDONLY | O_NOCTTY); + fd = open(pathname, O_RDONLY | O_NOCTTY | O_NDELAY); if (fd < 0) { fprintf(stderr, "%s: failed to open '%s': %s\n", progname, pathname, strerror(errno)); @@ -224,6 +224,7 @@ lfs_project_handle_dir(struct list_head *head, const char *pathname, struct dirent *ent; DIR *dir; int ret = 0; + int rc; dir = opendir(pathname); if (dir == NULL) { @@ -233,24 +234,31 @@ lfs_project_handle_dir(struct list_head *head, const char *pathname, return ret; } - while (ret == 0 && (ent = readdir(dir)) != NULL) { + while ((ent = readdir(dir)) != NULL) { /* skip "." and ".." */ if (strcmp(ent->d_name, ".") == 0 || strcmp(ent->d_name, "..") == 0) continue; - if (strlen(ent->d_name) + strlen(pathname) >= - sizeof(fullname) + 1) { + if (strlen(ent->d_name) + strlen(pathname) + 1 >= + sizeof(fullname)) { ret = -ENAMETOOLONG; errno = ENAMETOOLONG; - break; + fprintf(stderr, "%s: ignored too long path: %s/%s\n", + progname, pathname, ent->d_name); + continue; } snprintf(fullname, PATH_MAX, "%s/%s", pathname, ent->d_name); - ret = func(fullname, phc); - if (phc->recursive && ret == 0 && ent->d_type == DT_DIR) - ret = lfs_project_item_alloc(head, fullname); + rc = func(fullname, phc); + if (rc && !ret) + ret = rc; + if (phc->recursive && ent->d_type == DT_DIR) { + rc = lfs_project_item_alloc(head, fullname); + if (rc && !ret) + ret = rc; + } } if (ret) @@ -270,7 +278,7 @@ static int lfs_project_iterate(const char *pathname, struct list_head head; struct stat st; int ret = 0; - bool top_dir = true; + int rc = 0; ret = stat(pathname, &st); if (ret) { @@ -296,16 +304,13 @@ static int lfs_project_iterate(const char *pathname, while (!list_empty(&head)) { lpi = list_entry(head.next, struct lfs_project_item, lpi_list); list_del(&lpi->lpi_list); - if (ret == 0) { - ret = lfs_project_handle_dir(&head, lpi->lpi_pathname, + if (rc == 0) { + rc = lfs_project_handle_dir(&head, lpi->lpi_pathname, phc, func); - /* only ignore ENOENT error if this is - * not top directory. */ - if (ret == -ENOENT && !top_dir) - ret = 0; + if (!ret && rc) + ret = rc; } free(lpi); - top_dir = false; } return ret;