Skip to content

Commit

Permalink
---
Browse files Browse the repository at this point in the history
yaml
---
r: 300372
b: refs/heads/master
c: 94753db
h: refs/heads/master
v: v3
  • Loading branch information
Linus Torvalds committed May 11, 2012
1 parent 71fb54b commit ca92722
Show file tree
Hide file tree
Showing 2 changed files with 27 additions and 29 deletions.
2 changes: 1 addition & 1 deletion [refs]
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
---
refs/heads/master: 8c01a529b861ba97c7d78368e6a5d4d42e946f75
refs/heads/master: 94753db5ed9ad97582ef453127d9626a7a2be602
54 changes: 26 additions & 28 deletions trunk/fs/dcache.c
Original file line number Diff line number Diff line change
Expand Up @@ -153,30 +153,9 @@ int proc_nr_dentry(ctl_table *table, int write, void __user *buffer,
* In contrast, 'ct' and 'tcount' can be from a pathname, and do
* need the careful unaligned handling.
*/
static inline int dentry_cmp(const struct dentry *dentry, const unsigned char *ct, unsigned tcount)
static inline int dentry_string_cmp(const unsigned char *cs, const unsigned char *ct, unsigned tcount)
{
unsigned long a,b,mask;
const unsigned char *cs;

if (unlikely(dentry->d_name.len != tcount))
return 1;
/*
* Be careful about RCU walk racing with rename:
* use ACCESS_ONCE to fetch the name pointer.
*
* NOTE! Even if a rename will mean that the length
* was not loaded atomically, we don't care. The
* RCU walk will check the sequence count eventually,
* and catch it. And we won't overrun the buffer,
* because we're reading the name pointer atomically,
* and a dentry name is guaranteed to be properly
* terminated with a NUL byte.
*
* End result: even if 'len' is wrong, we'll exit
* early because the data cannot match (there can
* be no NUL in the ct/tcount data)
*/
cs = ACCESS_ONCE(dentry->d_name.name);

for (;;) {
a = *(unsigned long *)cs;
Expand All @@ -197,13 +176,8 @@ static inline int dentry_cmp(const struct dentry *dentry, const unsigned char *c

#else

static inline int dentry_cmp(const struct dentry *dentry, const unsigned char *ct, unsigned tcount)
static inline int dentry_string_cmp(const unsigned char *cs, const unsigned char *ct, unsigned tcount)
{
const unsigned char *cs = dentry->d_name.name;

if (dentry->d_name.len != tcount)
return 1;

do {
if (*cs != *ct)
return 1;
Expand All @@ -216,6 +190,30 @@ static inline int dentry_cmp(const struct dentry *dentry, const unsigned char *c

#endif

static inline int dentry_cmp(const struct dentry *dentry, const unsigned char *ct, unsigned tcount)
{
if (dentry->d_name.len != tcount)
return 1;

/*
* Be careful about RCU walk racing with rename:
* use ACCESS_ONCE to fetch the name pointer.
*
* NOTE! Even if a rename will mean that the length
* was not loaded atomically, we don't care. The
* RCU walk will check the sequence count eventually,
* and catch it. And we won't overrun the buffer,
* because we're reading the name pointer atomically,
* and a dentry name is guaranteed to be properly
* terminated with a NUL byte.
*
* End result: even if 'len' is wrong, we'll exit
* early because the data cannot match (there can
* be no NUL in the ct/tcount data)
*/
return dentry_string_cmp(ACCESS_ONCE(dentry->d_name.name), ct, tcount);
}

static void __d_free(struct rcu_head *head)
{
struct dentry *dentry = container_of(head, struct dentry, d_u.d_rcu);
Expand Down

0 comments on commit ca92722

Please sign in to comment.