mkfifo $dir/fifo || error "failed to create fifo file"
$LFS find $dir -t p --printf "%p %y %LP\n" ||
- error "should not fail even cannot get projid from pipe file"
+ error "should not fail when getting projid from pipe file"
found=$($LFS find $dir -t p --printf "%y")
[[ "p" == $found ]] || error "found $found, expect p"
mknod $dir/chardev c 1 5 ||
error "failed to create character device file"
$LFS find $dir -t c --printf "%p %y %LP\n" ||
- error "should not fail even cannot get projid from chardev file"
+ error "should not fail when getting projid from chardev file"
found=$($LFS find $dir -t c --printf "%y")
[[ "c" == $found ]] || error "found $found, expect c"
}
run_test 56eh "check lfs find --skip"
+test_56ei() {
+ local path=$DIR/$tdir
+ local projid=1234
+ local expected_count=3
+
+ # Create test dir containing:
+ # - regular file, with default projid
+ # - regular file, with unique projid
+ # - symbolic link, with unique projid
+ # - special char dev file, with unique projid
+ test_mkdir $path || error "mkdir $path failed"
+ touch $path/file0 $path/file$projid || error "touch failed"
+ ln -s $path/file$projid $path/link$projid
+ mknod $path/char$projid c 1 3
+ $LFS project -p $projid -s $path/file$projid
+ $LFS project -p $projid -s $path/link$projid
+ $LFS project -p $projid -s $path/char$projid
+ stack_trap "rm -rf $path" EXIT
+
+ $LFS project -r $path/
+ echo -e "Actual output:\n$($LFS find $path --printf '%LP %p\n')"
+
+ # Find all files and print their projids along with their path; count
+ found_count=$($LFS find $path --printf "%LP %p\n" |
+ grep -E "$projid $path/(link|char|file)$projid" | wc -l)
+ echo -e "found_count: $found_count"
+ [[ $found_count == $expected_count ]] ||
+ error "Did not find any entries with expected projid $projid"
+
+}
+run_test 56ei "test lfs find --printf prints correct projid for special files"
+
test_57a() {
[ $PARALLEL == "yes" ] && skip "skip parallel run"
# note test will not do anything if MDS is not local
#define FORMATTED_BUF_LEN 1024
-#ifndef INVALID_PROJID
-#define INVALID_PROJID -1
+#ifndef DEFAULT_PROJID
+#define DEFAULT_PROJID 0
#endif
static int llapi_msg_level = LLAPI_MSG_MAX;
*wrote = snprintf(buffer, size, DFID_NOBRACE, PFID(&fid));
goto format_done;
case 'P':
- if (projid == INVALID_PROJID)
- *wrote = snprintf(buffer, size, "-1");
- else
- *wrote = snprintf(buffer, size, "%u", projid);
+ *wrote = snprintf(buffer, size, "%u", projid);
goto format_done;
case 'a': /* file attributes */
longopt = false;
}
/*
- * Get file/directory project id.
- * by the open fd resides on.
- * Return 0 and project id on success, or -ve errno.
+ * Gets the project id of a file, directory, or special file,
+ * and stores it at the projid memory address passed in.
+ * Returns 0 on success, or -errno for failure.
+ *
+ * @param[in] path The full path of the file or directory we're trying
+ * to retrieve the project id for.
+ * @param[in] fd A reference to the file descriptor of either the file
+ * or directory we're inspecting. The file/dir may or may
+ * not have been already opened, but if not, we'll open
+ * it here (for regular files/directories).
+ * @param[in] mode The mode type of the file. This will tell us if the file
+ * is a regular file/dir or if it's a special file type.
+ * @param[out] projid A reference to where to store the projid of the file/dir
*/
-static int fget_projid(int fd, __u32 *projid)
+static int get_projid(const char *path, int *fd, mode_t mode, __u32 *projid)
{
- struct fsxattr fsx;
- int rc;
+ struct fsxattr fsx = { 0 };
+ struct lu_project lu_project = { 0 };
+ int ret = 0;
- rc = ioctl(fd, FS_IOC_FSGETXATTR, &fsx);
- if (rc) {
- *projid = INVALID_PROJID;
- return -errno;
+ /* Check the mode of the file */
+ if (S_ISREG(mode) || S_ISDIR(mode)) {
+ /* This is a regular file type or directory */
+ if (*fd < 0) {
+ /* If we haven't yet opened the file,
+ * open it in read-only mode
+ */
+ *fd = open(path, O_RDONLY | O_NOCTTY | O_NDELAY);
+ if (*fd <= 0) {
+ llapi_error(LLAPI_MSG_ERROR, -ENOENT,
+ "warning: %s: unable to open file \"%s\"to get project id",
+ __func__, path);
+ return -ENOENT;
+ }
+ }
+ ret = ioctl(*fd, FS_IOC_FSGETXATTR, &fsx);
+ if (ret)
+ return -errno;
+
+ *projid = fsx.fsx_projid;
+ } else {
+ /* This is a special file type, like a symbolic link, block or
+ * character device file. We'll have to open its parent
+ * directory and get metadata about the file through that.
+ */
+ char dir_path[PATH_MAX + 1] = { 0 };
+ char base_path[PATH_MAX + 1] = { 0 };
+
+ strncpy(dir_path, path, PATH_MAX);
+ strncpy(base_path, path, PATH_MAX);
+ char *dir_name = dirname(dir_path);
+ char *base_name = basename(base_path);
+ int dir_fd = open(dir_name, O_RDONLY | O_NOCTTY | O_NDELAY);
+
+ if (dir_fd < 0) {
+ llapi_error(LLAPI_MSG_ERROR, -ENOENT,
+ "warning: %s: unable to open dir \"%s\"to get project id",
+ __func__, path);
+ return -errno;
+ }
+ lu_project.project_type = LU_PROJECT_GET;
+ if (base_name)
+ strncpy(lu_project.project_name, base_name, NAME_MAX);
+
+ ret = ioctl(dir_fd, LL_IOC_PROJECT, &lu_project);
+ if (ret) {
+ llapi_error(LLAPI_MSG_ERROR, -ENOENT,
+ "warning: %s: failed to get xattr for '%s': %s",
+ __func__, path, strerror(errno));
+ return -errno;
+ }
+ *projid = lu_project.project_id;
+ close(dir_fd);
}
- *projid = fsx.fsx_projid;
return 0;
}
__u32 stripe_count = 0;
__u64 flags;
int fd = -2;
- __u32 projid = INVALID_PROJID;
+ __u32 projid = DEFAULT_PROJID;
bool gather_all = false;
if (p == -1 && d == -1)
}
}
+ /* Retrieve project id from file/dir */
if (param->fp_check_projid || gather_all) {
- if (fd == -2)
- fd = open(path, O_RDONLY | O_NONBLOCK);
-
- if (fd > 0)
- ret = fget_projid(fd, &projid);
- else
- ret = -errno;
+ ret = get_projid(path, &fd, lmd->lmd_stx.stx_mode, &projid);
+ if (ret) {
+ llapi_error(LLAPI_MSG_ERROR, -ENOENT,
+ "warning: %s: failed to get project id from file \"%s\"",
+ __func__, path);
+ goto out;
+ }
if (param->fp_check_projid) {
- if (ret)
- goto out;
- if (projid == param->fp_projid) {
- if (param->fp_exclude_projid)
- goto decided;
- } else {
- if (!param->fp_exclude_projid)
- goto decided;
- }
+ /* Conditionally filter this result based on --projid
+ * param, and whether or not we're including or
+ * excluding matching results.
+ * fp_exclude_projid = 0 means only include exact match.
+ * fp_exclude_projid = 1 means exclude exact match.
+ */
+ bool matches = projid == param->fp_projid;
+
+ if (matches == param->fp_exclude_projid)
+ goto decided;
}
}