Skip to content

Commit

Permalink
Merge branch 'for-4.9' of git://git.kernel.org/pub/scm/linux/kernel/g…
Browse files Browse the repository at this point in the history
…it/tj/cgroup

Pull cgroup updates from Tejun Heo:

 - tracepoints for basic cgroup management operations added

 - kernfs and cgroup path formatting functions updated to behave in the
   style of strlcpy()

 - non-critical bug fixes

* 'for-4.9' of git://git.kernel.org/pub/scm/linux/kernel/git/tj/cgroup:
  blkcg: Unlock blkcg_pol_mutex only once when cpd == NULL
  cgroup: fix error handling regressions in proc_cgroup_show() and cgroup_release_agent()
  cpuset: fix error handling regression in proc_cpuset_show()
  cgroup: add tracepoints for basic operations
  cgroup: make cgroup_path() and friends behave in the style of strlcpy()
  kernfs: remove kernfs_path_len()
  kernfs: make kernfs_path*() behave in the style of strlcpy()
  kernfs: add dummy implementation of kernfs_path_from_node()
  • Loading branch information
torvalds committed Oct 14, 2016
2 parents b6daa51 + bbb427e commit f34d360
Show file tree
Hide file tree
Showing 10 changed files with 266 additions and 130 deletions.
4 changes: 1 addition & 3 deletions block/blk-cgroup.c
Original file line number Diff line number Diff line change
Expand Up @@ -1340,10 +1340,8 @@ int blkcg_policy_register(struct blkcg_policy *pol)
struct blkcg_policy_data *cpd;

cpd = pol->cpd_alloc_fn(GFP_KERNEL);
if (!cpd) {
mutex_unlock(&blkcg_pol_mutex);
if (!cpd)
goto err_free_cpds;
}

blkcg->cpd[pol->plid] = cpd;
cpd->blkcg = blkcg;
Expand Down
84 changes: 17 additions & 67 deletions fs/kernfs/dir.c
Original file line number Diff line number Diff line change
Expand Up @@ -110,18 +110,18 @@ static struct kernfs_node *kernfs_common_ancestor(struct kernfs_node *a,
* kn_to: /n1/n2/n3 [depth=3]
* result: /../..
*
* return value: length of the string. If greater than buflen,
* then contents of buf are undefined. On error, -1 is returned.
* Returns the length of the full path. If the full length is equal to or
* greater than @buflen, @buf contains the truncated path with the trailing
* '\0'. On error, -errno is returned.
*/
static int kernfs_path_from_node_locked(struct kernfs_node *kn_to,
struct kernfs_node *kn_from,
char *buf, size_t buflen)
{
struct kernfs_node *kn, *common;
const char parent_str[] = "/..";
size_t depth_from, depth_to, len = 0, nlen = 0;
char *p;
int i;
size_t depth_from, depth_to, len = 0;
int i, j;

if (!kn_from)
kn_from = kernfs_root(kn_to)->kn;
Expand All @@ -131,7 +131,7 @@ static int kernfs_path_from_node_locked(struct kernfs_node *kn_to,

common = kernfs_common_ancestor(kn_from, kn_to);
if (WARN_ON(!common))
return -1;
return -EINVAL;

depth_to = kernfs_depth(common, kn_to);
depth_from = kernfs_depth(common, kn_from);
Expand All @@ -144,22 +144,16 @@ static int kernfs_path_from_node_locked(struct kernfs_node *kn_to,
len < buflen ? buflen - len : 0);

/* Calculate how many bytes we need for the rest */
for (kn = kn_to; kn != common; kn = kn->parent)
nlen += strlen(kn->name) + 1;

if (len + nlen >= buflen)
return len + nlen;

p = buf + len + nlen;
*p = '\0';
for (kn = kn_to; kn != common; kn = kn->parent) {
size_t tmp = strlen(kn->name);
p -= tmp;
memcpy(p, kn->name, tmp);
*(--p) = '/';
for (i = depth_to - 1; i >= 0; i--) {
for (kn = kn_to, j = 0; j < i; j++)
kn = kn->parent;
len += strlcpy(buf + len, "/",
len < buflen ? buflen - len : 0);
len += strlcpy(buf + len, kn->name,
len < buflen ? buflen - len : 0);
}

return len + nlen;
return len;
}

/**
Expand All @@ -185,29 +179,6 @@ int kernfs_name(struct kernfs_node *kn, char *buf, size_t buflen)
return ret;
}

/**
* kernfs_path_len - determine the length of the full path of a given node
* @kn: kernfs_node of interest
*
* The returned length doesn't include the space for the terminating '\0'.
*/
size_t kernfs_path_len(struct kernfs_node *kn)
{
size_t len = 0;
unsigned long flags;

spin_lock_irqsave(&kernfs_rename_lock, flags);

do {
len += strlen(kn->name) + 1;
kn = kn->parent;
} while (kn && kn->parent);

spin_unlock_irqrestore(&kernfs_rename_lock, flags);

return len;
}

/**
* kernfs_path_from_node - build path of node @to relative to @from.
* @from: parent kernfs_node relative to which we need to build the path
Expand All @@ -220,8 +191,9 @@ size_t kernfs_path_len(struct kernfs_node *kn)
* path (which includes '..'s) as needed to reach from @from to @to is
* returned.
*
* If @buf isn't long enough, the return value will be greater than @buflen
* and @buf contents are undefined.
* Returns the length of the full path. If the full length is equal to or
* greater than @buflen, @buf contains the truncated path with the trailing
* '\0'. On error, -errno is returned.
*/
int kernfs_path_from_node(struct kernfs_node *to, struct kernfs_node *from,
char *buf, size_t buflen)
Expand All @@ -236,28 +208,6 @@ int kernfs_path_from_node(struct kernfs_node *to, struct kernfs_node *from,
}
EXPORT_SYMBOL_GPL(kernfs_path_from_node);

/**
* kernfs_path - build full path of a given node
* @kn: kernfs_node of interest
* @buf: buffer to copy @kn's name into
* @buflen: size of @buf
*
* Builds and returns the full path of @kn in @buf of @buflen bytes. The
* path is built from the end of @buf so the returned pointer usually
* doesn't match @buf. If @buf isn't long enough, @buf is nul terminated
* and %NULL is returned.
*/
char *kernfs_path(struct kernfs_node *kn, char *buf, size_t buflen)
{
int ret;

ret = kernfs_path_from_node(kn, NULL, buf, buflen);
if (ret < 0 || ret >= buflen)
return NULL;
return buf;
}
EXPORT_SYMBOL_GPL(kernfs_path);

/**
* pr_cont_kernfs_name - pr_cont name of a kernfs_node
* @kn: kernfs_node of interest
Expand Down
6 changes: 3 additions & 3 deletions fs/sysfs/dir.c
Original file line number Diff line number Diff line change
Expand Up @@ -21,14 +21,14 @@ DEFINE_SPINLOCK(sysfs_symlink_target_lock);

void sysfs_warn_dup(struct kernfs_node *parent, const char *name)
{
char *buf, *path = NULL;
char *buf;

buf = kzalloc(PATH_MAX, GFP_KERNEL);
if (buf)
path = kernfs_path(parent, buf, PATH_MAX);
kernfs_path(parent, buf, PATH_MAX);

WARN(1, KERN_WARNING "sysfs: cannot create duplicate filename '%s/%s'\n",
path, name);
buf, name);

kfree(buf);
}
Expand Down
11 changes: 1 addition & 10 deletions include/linux/blk-cgroup.h
Original file line number Diff line number Diff line change
Expand Up @@ -343,16 +343,7 @@ static inline struct blkcg *cpd_to_blkcg(struct blkcg_policy_data *cpd)
*/
static inline int blkg_path(struct blkcg_gq *blkg, char *buf, int buflen)
{
char *p;

p = cgroup_path(blkg->blkcg->css.cgroup, buf, buflen);
if (!p) {
strncpy(buf, "<unavailable>", buflen);
return -ENAMETOOLONG;
}

memmove(buf, p, buf + buflen - p);
return 0;
return cgroup_path(blkg->blkcg->css.cgroup, buf, buflen);
}

/**
Expand Down
9 changes: 4 additions & 5 deletions include/linux/cgroup.h
Original file line number Diff line number Diff line change
Expand Up @@ -97,7 +97,7 @@ int cgroup_add_legacy_cftypes(struct cgroup_subsys *ss, struct cftype *cfts);
int cgroup_rm_cftypes(struct cftype *cfts);
void cgroup_file_notify(struct cgroup_file *cfile);

char *task_cgroup_path(struct task_struct *task, char *buf, size_t buflen);
int task_cgroup_path(struct task_struct *task, char *buf, size_t buflen);
int cgroupstats_build(struct cgroupstats *stats, struct dentry *dentry);
int proc_cgroup_show(struct seq_file *m, struct pid_namespace *ns,
struct pid *pid, struct task_struct *tsk);
Expand Down Expand Up @@ -555,8 +555,7 @@ static inline int cgroup_name(struct cgroup *cgrp, char *buf, size_t buflen)
return kernfs_name(cgrp->kn, buf, buflen);
}

static inline char * __must_check cgroup_path(struct cgroup *cgrp, char *buf,
size_t buflen)
static inline int cgroup_path(struct cgroup *cgrp, char *buf, size_t buflen)
{
return kernfs_path(cgrp->kn, buf, buflen);
}
Expand Down Expand Up @@ -658,8 +657,8 @@ struct cgroup_namespace *copy_cgroup_ns(unsigned long flags,
struct user_namespace *user_ns,
struct cgroup_namespace *old_ns);

char *cgroup_path_ns(struct cgroup *cgrp, char *buf, size_t buflen,
struct cgroup_namespace *ns);
int cgroup_path_ns(struct cgroup *cgrp, char *buf, size_t buflen,
struct cgroup_namespace *ns);

#else /* !CONFIG_CGROUPS */

Expand Down
28 changes: 20 additions & 8 deletions include/linux/kernfs.h
Original file line number Diff line number Diff line change
Expand Up @@ -269,10 +269,8 @@ static inline bool kernfs_ns_enabled(struct kernfs_node *kn)
}

int kernfs_name(struct kernfs_node *kn, char *buf, size_t buflen);
size_t kernfs_path_len(struct kernfs_node *kn);
int kernfs_path_from_node(struct kernfs_node *root_kn, struct kernfs_node *kn,
char *buf, size_t buflen);
char *kernfs_path(struct kernfs_node *kn, char *buf, size_t buflen);
void pr_cont_kernfs_name(struct kernfs_node *kn);
void pr_cont_kernfs_path(struct kernfs_node *kn);
struct kernfs_node *kernfs_get_parent(struct kernfs_node *kn);
Expand Down Expand Up @@ -341,12 +339,10 @@ static inline bool kernfs_ns_enabled(struct kernfs_node *kn)
static inline int kernfs_name(struct kernfs_node *kn, char *buf, size_t buflen)
{ return -ENOSYS; }

static inline size_t kernfs_path_len(struct kernfs_node *kn)
{ return 0; }

static inline char *kernfs_path(struct kernfs_node *kn, char *buf,
size_t buflen)
{ return NULL; }
static inline int kernfs_path_from_node(struct kernfs_node *root_kn,
struct kernfs_node *kn,
char *buf, size_t buflen)
{ return -ENOSYS; }

static inline void pr_cont_kernfs_name(struct kernfs_node *kn) { }
static inline void pr_cont_kernfs_path(struct kernfs_node *kn) { }
Expand Down Expand Up @@ -436,6 +432,22 @@ static inline void kernfs_init(void) { }

#endif /* CONFIG_KERNFS */

/**
* kernfs_path - build full path of a given node
* @kn: kernfs_node of interest
* @buf: buffer to copy @kn's name into
* @buflen: size of @buf
*
* Builds and returns the full path of @kn in @buf of @buflen bytes. The
* path is built from the end of @buf so the returned pointer usually
* doesn't match @buf. If @buf isn't long enough, @buf is nul terminated
* and %NULL is returned.
*/
static inline int kernfs_path(struct kernfs_node *kn, char *buf, size_t buflen)
{
return kernfs_path_from_node(kn, NULL, buf, buflen);
}

static inline struct kernfs_node *
kernfs_find_and_get(struct kernfs_node *kn, const char *name)
{
Expand Down
Loading

0 comments on commit f34d360

Please sign in to comment.