Lines 88-122
EXPORT_SYMBOL(rename_lock);
Link Here
|
88 |
|
88 |
|
89 |
static struct kmem_cache *dentry_cache __read_mostly; |
89 |
static struct kmem_cache *dentry_cache __read_mostly; |
90 |
|
90 |
|
91 |
/** |
|
|
92 |
* read_seqbegin_or_lock - begin a sequence number check or locking block |
93 |
* @lock: sequence lock |
94 |
* @seq : sequence number to be checked |
95 |
* |
96 |
* First try it once optimistically without taking the lock. If that fails, |
97 |
* take the lock. The sequence number is also used as a marker for deciding |
98 |
* whether to be a reader (even) or writer (odd). |
99 |
* N.B. seq must be initialized to an even number to begin with. |
100 |
*/ |
101 |
static inline void read_seqbegin_or_lock(seqlock_t *lock, int *seq) |
102 |
{ |
103 |
if (!(*seq & 1)) /* Even */ |
104 |
*seq = read_seqbegin(lock); |
105 |
else /* Odd */ |
106 |
read_seqlock_excl(lock); |
107 |
} |
108 |
|
109 |
static inline int need_seqretry(seqlock_t *lock, int seq) |
110 |
{ |
111 |
return !(seq & 1) && read_seqretry(lock, seq); |
112 |
} |
113 |
|
114 |
static inline void done_seqretry(seqlock_t *lock, int seq) |
115 |
{ |
116 |
if (seq & 1) |
117 |
read_sequnlock_excl(lock); |
118 |
} |
119 |
|
120 |
/* |
91 |
/* |
121 |
* This is the single most critical data structure when it comes |
92 |
* This is the single most critical data structure when it comes |
122 |
* to the dcache: the hashtable for lookups. Somebody should try |
93 |
* to the dcache: the hashtable for lookups. Somebody should try |
Lines 1191-1197
void shrink_dcache_for_umount(struct super_block *sb)
Link Here
|
1191 |
* the parenthood after dropping the lock and check |
1162 |
* the parenthood after dropping the lock and check |
1192 |
* that the sequence number still matches. |
1163 |
* that the sequence number still matches. |
1193 |
*/ |
1164 |
*/ |
1194 |
static struct dentry *try_to_ascend(struct dentry *old, unsigned seq) |
1165 |
static struct dentry *try_to_ascend(struct dentry *old, int locked, unsigned seq) |
1195 |
{ |
1166 |
{ |
1196 |
struct dentry *new = old->d_parent; |
1167 |
struct dentry *new = old->d_parent; |
1197 |
|
1168 |
|
Lines 1205-1211
static struct dentry *try_to_ascend(struct dentry *old, unsigned seq)
Link Here
|
1205 |
*/ |
1176 |
*/ |
1206 |
if (new != old->d_parent || |
1177 |
if (new != old->d_parent || |
1207 |
(old->d_flags & DCACHE_DENTRY_KILLED) || |
1178 |
(old->d_flags & DCACHE_DENTRY_KILLED) || |
1208 |
need_seqretry(&rename_lock, seq)) { |
1179 |
(!locked && read_seqretry(&rename_lock, seq))) { |
1209 |
spin_unlock(&new->d_lock); |
1180 |
spin_unlock(&new->d_lock); |
1210 |
new = NULL; |
1181 |
new = NULL; |
1211 |
} |
1182 |
} |
Lines 1242-1253
static void d_walk(struct dentry *parent, void *data,
Link Here
|
1242 |
{ |
1213 |
{ |
1243 |
struct dentry *this_parent; |
1214 |
struct dentry *this_parent; |
1244 |
struct list_head *next; |
1215 |
struct list_head *next; |
1245 |
unsigned seq = 0; |
1216 |
unsigned seq; |
|
|
1217 |
int locked = 0; |
1246 |
enum d_walk_ret ret; |
1218 |
enum d_walk_ret ret; |
1247 |
bool retry = true; |
1219 |
bool retry = true; |
1248 |
|
1220 |
|
|
|
1221 |
seq = read_seqbegin(&rename_lock); |
1249 |
again: |
1222 |
again: |
1250 |
read_seqbegin_or_lock(&rename_lock, &seq); |
|
|
1251 |
this_parent = parent; |
1223 |
this_parent = parent; |
1252 |
spin_lock(&this_parent->d_lock); |
1224 |
spin_lock(&this_parent->d_lock); |
1253 |
|
1225 |
|
Lines 1301-1313
resume:
Link Here
|
1301 |
*/ |
1273 |
*/ |
1302 |
if (this_parent != parent) { |
1274 |
if (this_parent != parent) { |
1303 |
struct dentry *child = this_parent; |
1275 |
struct dentry *child = this_parent; |
1304 |
this_parent = try_to_ascend(this_parent, seq); |
1276 |
this_parent = try_to_ascend(this_parent, locked, seq); |
1305 |
if (!this_parent) |
1277 |
if (!this_parent) |
1306 |
goto rename_retry; |
1278 |
goto rename_retry; |
1307 |
next = child->d_u.d_child.next; |
1279 |
next = child->d_u.d_child.next; |
1308 |
goto resume; |
1280 |
goto resume; |
1309 |
} |
1281 |
} |
1310 |
if (need_seqretry(&rename_lock, seq)) { |
1282 |
if (!locked && read_seqretry(&rename_lock, seq)) { |
1311 |
spin_unlock(&this_parent->d_lock); |
1283 |
spin_unlock(&this_parent->d_lock); |
1312 |
goto rename_retry; |
1284 |
goto rename_retry; |
1313 |
} |
1285 |
} |
Lines 1316-1328
resume:
Link Here
|
1316 |
|
1288 |
|
1317 |
out_unlock: |
1289 |
out_unlock: |
1318 |
spin_unlock(&this_parent->d_lock); |
1290 |
spin_unlock(&this_parent->d_lock); |
1319 |
done_seqretry(&rename_lock, seq); |
1291 |
if (locked) |
|
|
1292 |
write_sequnlock(&rename_lock); |
1320 |
return; |
1293 |
return; |
1321 |
|
1294 |
|
1322 |
rename_retry: |
1295 |
rename_retry: |
1323 |
if (!retry) |
1296 |
if (!retry) |
1324 |
return; |
1297 |
return; |
1325 |
seq = 1; |
1298 |
if (locked) |
|
|
1299 |
goto again; |
1300 |
locked = 1; |
1301 |
write_seqlock(&rename_lock); |
1326 |
goto again; |
1302 |
goto again; |
1327 |
} |
1303 |
} |
1328 |
|
1304 |
|
Lines 2825-2863
static int prepend(char **buffer, int *buflen, const char *str, int namelen)
Link Here
|
2825 |
return 0; |
2801 |
return 0; |
2826 |
} |
2802 |
} |
2827 |
|
2803 |
|
2828 |
/** |
|
|
2829 |
* prepend_name - prepend a pathname in front of current buffer pointer |
2830 |
* @buffer: buffer pointer |
2831 |
* @buflen: allocated length of the buffer |
2832 |
* @name: name string and length qstr structure |
2833 |
* |
2834 |
* With RCU path tracing, it may race with d_move(). Use ACCESS_ONCE() to |
2835 |
* make sure that either the old or the new name pointer and length are |
2836 |
* fetched. However, there may be mismatch between length and pointer. |
2837 |
* The length cannot be trusted, we need to copy it byte-by-byte until |
2838 |
* the length is reached or a null byte is found. It also prepends "/" at |
2839 |
* the beginning of the name. The sequence number check at the caller will |
2840 |
* retry it again when a d_move() does happen. So any garbage in the buffer |
2841 |
* due to mismatched pointer and length will be discarded. |
2842 |
*/ |
2843 |
static int prepend_name(char **buffer, int *buflen, struct qstr *name) |
2804 |
static int prepend_name(char **buffer, int *buflen, struct qstr *name) |
2844 |
{ |
2805 |
{ |
2845 |
const char *dname = ACCESS_ONCE(name->name); |
2806 |
return prepend(buffer, buflen, name->name, name->len); |
2846 |
u32 dlen = ACCESS_ONCE(name->len); |
|
|
2847 |
char *p; |
2848 |
|
2849 |
if (*buflen < dlen + 1) |
2850 |
return -ENAMETOOLONG; |
2851 |
*buflen -= dlen + 1; |
2852 |
p = *buffer -= dlen + 1; |
2853 |
*p++ = '/'; |
2854 |
while (dlen--) { |
2855 |
char c = *dname++; |
2856 |
if (!c) |
2857 |
break; |
2858 |
*p++ = c; |
2859 |
} |
2860 |
return 0; |
2861 |
} |
2807 |
} |
2862 |
|
2808 |
|
2863 |
/** |
2809 |
/** |
Lines 2867-2881
static int prepend_name(char **buffer, int *buflen, struct qstr *name)
Link Here
|
2867 |
* @buffer: pointer to the end of the buffer |
2813 |
* @buffer: pointer to the end of the buffer |
2868 |
* @buflen: pointer to buffer length |
2814 |
* @buflen: pointer to buffer length |
2869 |
* |
2815 |
* |
2870 |
* The function will first try to write out the pathname without taking any |
2816 |
* Caller holds the rename_lock. |
2871 |
* lock other than the RCU read lock to make sure that dentries won't go away. |
|
|
2872 |
* It only checks the sequence number of the global rename_lock as any change |
2873 |
* in the dentry's d_seq will be preceded by changes in the rename_lock |
2874 |
* sequence number. If the sequence number had been changed, it will restart |
2875 |
* the whole pathname back-tracing sequence again by taking the rename_lock. |
2876 |
* In this case, there is no need to take the RCU read lock as the recursive |
2877 |
* parent pointer references will keep the dentry chain alive as long as no |
2878 |
* rename operation is performed. |
2879 |
*/ |
2817 |
*/ |
2880 |
static int prepend_path(const struct path *path, |
2818 |
static int prepend_path(const struct path *path, |
2881 |
const struct path *root, |
2819 |
const struct path *root, |
Lines 2884-2949
static int prepend_path(const struct path *path,
Link Here
|
2884 |
struct dentry *dentry = path->dentry; |
2822 |
struct dentry *dentry = path->dentry; |
2885 |
struct vfsmount *vfsmnt = path->mnt; |
2823 |
struct vfsmount *vfsmnt = path->mnt; |
2886 |
struct mount *mnt = real_mount(vfsmnt); |
2824 |
struct mount *mnt = real_mount(vfsmnt); |
|
|
2825 |
bool slash = false; |
2887 |
int error = 0; |
2826 |
int error = 0; |
2888 |
unsigned seq = 0; |
|
|
2889 |
char *bptr; |
2890 |
int blen; |
2891 |
|
2827 |
|
2892 |
rcu_read_lock(); |
|
|
2893 |
restart: |
2894 |
bptr = *buffer; |
2895 |
blen = *buflen; |
2896 |
read_seqbegin_or_lock(&rename_lock, &seq); |
2897 |
while (dentry != root->dentry || vfsmnt != root->mnt) { |
2828 |
while (dentry != root->dentry || vfsmnt != root->mnt) { |
2898 |
struct dentry * parent; |
2829 |
struct dentry * parent; |
2899 |
|
2830 |
|
2900 |
if (dentry == vfsmnt->mnt_root || IS_ROOT(dentry)) { |
2831 |
if (dentry == vfsmnt->mnt_root || IS_ROOT(dentry)) { |
2901 |
/* Global root? */ |
2832 |
/* Global root? */ |
2902 |
if (mnt_has_parent(mnt)) { |
2833 |
if (!mnt_has_parent(mnt)) |
2903 |
dentry = mnt->mnt_mountpoint; |
2834 |
goto global_root; |
2904 |
mnt = mnt->mnt_parent; |
2835 |
dentry = mnt->mnt_mountpoint; |
2905 |
vfsmnt = &mnt->mnt; |
2836 |
mnt = mnt->mnt_parent; |
2906 |
continue; |
2837 |
vfsmnt = &mnt->mnt; |
2907 |
} |
2838 |
continue; |
2908 |
/* |
|
|
2909 |
* Filesystems needing to implement special "root names" |
2910 |
* should do so with ->d_dname() |
2911 |
*/ |
2912 |
if (IS_ROOT(dentry) && |
2913 |
(dentry->d_name.len != 1 || |
2914 |
dentry->d_name.name[0] != '/')) { |
2915 |
WARN(1, "Root dentry has weird name <%.*s>\n", |
2916 |
(int) dentry->d_name.len, |
2917 |
dentry->d_name.name); |
2918 |
} |
2919 |
if (!error) |
2920 |
error = is_mounted(vfsmnt) ? 1 : 2; |
2921 |
break; |
2922 |
} |
2839 |
} |
2923 |
parent = dentry->d_parent; |
2840 |
parent = dentry->d_parent; |
2924 |
prefetch(parent); |
2841 |
prefetch(parent); |
2925 |
error = prepend_name(&bptr, &blen, &dentry->d_name); |
2842 |
spin_lock(&dentry->d_lock); |
|
|
2843 |
error = prepend_name(buffer, buflen, &dentry->d_name); |
2844 |
spin_unlock(&dentry->d_lock); |
2845 |
if (!error) |
2846 |
error = prepend(buffer, buflen, "/", 1); |
2926 |
if (error) |
2847 |
if (error) |
2927 |
break; |
2848 |
break; |
2928 |
|
2849 |
|
|
|
2850 |
slash = true; |
2929 |
dentry = parent; |
2851 |
dentry = parent; |
2930 |
} |
2852 |
} |
2931 |
if (!(seq & 1)) |
|
|
2932 |
rcu_read_unlock(); |
2933 |
if (need_seqretry(&rename_lock, seq)) { |
2934 |
seq = 1; |
2935 |
goto restart; |
2936 |
} |
2937 |
done_seqretry(&rename_lock, seq); |
2938 |
|
2853 |
|
2939 |
if (error >= 0 && bptr == *buffer) { |
2854 |
if (!error && !slash) |
2940 |
if (--blen < 0) |
2855 |
error = prepend(buffer, buflen, "/", 1); |
2941 |
error = -ENAMETOOLONG; |
2856 |
|
2942 |
else |
2857 |
return error; |
2943 |
*--bptr = '/'; |
2858 |
|
2944 |
} |
2859 |
global_root: |
2945 |
*buffer = bptr; |
2860 |
/* |
2946 |
*buflen = blen; |
2861 |
* Filesystems needing to implement special "root names" |
|
|
2862 |
* should do so with ->d_dname() |
2863 |
*/ |
2864 |
if (IS_ROOT(dentry) && |
2865 |
(dentry->d_name.len != 1 || dentry->d_name.name[0] != '/')) { |
2866 |
WARN(1, "Root dentry has weird name <%.*s>\n", |
2867 |
(int) dentry->d_name.len, dentry->d_name.name); |
2868 |
} |
2869 |
if (!slash) |
2870 |
error = prepend(buffer, buflen, "/", 1); |
2871 |
if (!error) |
2872 |
error = is_mounted(vfsmnt) ? 1 : 2; |
2947 |
return error; |
2873 |
return error; |
2948 |
} |
2874 |
} |
2949 |
|
2875 |
|
Lines 2972-2978
char *__d_path(const struct path *path,
Link Here
|
2972 |
|
2898 |
|
2973 |
prepend(&res, &buflen, "\0", 1); |
2899 |
prepend(&res, &buflen, "\0", 1); |
2974 |
br_read_lock(&vfsmount_lock); |
2900 |
br_read_lock(&vfsmount_lock); |
|
|
2901 |
write_seqlock(&rename_lock); |
2975 |
error = prepend_path(path, root, &res, &buflen); |
2902 |
error = prepend_path(path, root, &res, &buflen); |
|
|
2903 |
write_sequnlock(&rename_lock); |
2976 |
br_read_unlock(&vfsmount_lock); |
2904 |
br_read_unlock(&vfsmount_lock); |
2977 |
|
2905 |
|
2978 |
if (error < 0) |
2906 |
if (error < 0) |
Lines 2991-2997
char *d_absolute_path(const struct path *path,
Link Here
|
2991 |
|
2919 |
|
2992 |
prepend(&res, &buflen, "\0", 1); |
2920 |
prepend(&res, &buflen, "\0", 1); |
2993 |
br_read_lock(&vfsmount_lock); |
2921 |
br_read_lock(&vfsmount_lock); |
|
|
2922 |
write_seqlock(&rename_lock); |
2994 |
error = prepend_path(path, &root, &res, &buflen); |
2923 |
error = prepend_path(path, &root, &res, &buflen); |
|
|
2924 |
write_sequnlock(&rename_lock); |
2995 |
br_read_unlock(&vfsmount_lock); |
2925 |
br_read_unlock(&vfsmount_lock); |
2996 |
|
2926 |
|
2997 |
if (error > 1) |
2927 |
if (error > 1) |
Lines 3068-3074
char *d_path(const struct path *path, char *buf, int buflen)
Link Here
|
3068 |
rcu_read_lock(); |
2998 |
rcu_read_lock(); |
3069 |
get_fs_root_rcu(current->fs, &root); |
2999 |
get_fs_root_rcu(current->fs, &root); |
3070 |
br_read_lock(&vfsmount_lock); |
3000 |
br_read_lock(&vfsmount_lock); |
|
|
3001 |
write_seqlock(&rename_lock); |
3071 |
error = path_with_deleted(path, &root, &res, &buflen); |
3002 |
error = path_with_deleted(path, &root, &res, &buflen); |
|
|
3003 |
write_sequnlock(&rename_lock); |
3072 |
br_read_unlock(&vfsmount_lock); |
3004 |
br_read_unlock(&vfsmount_lock); |
3073 |
rcu_read_unlock(); |
3005 |
rcu_read_unlock(); |
3074 |
|
3006 |
|
Lines 3104-3113
char *simple_dname(struct dentry *dentry, char *buffer, int buflen)
Link Here
|
3104 |
char *end = buffer + buflen; |
3036 |
char *end = buffer + buflen; |
3105 |
/* these dentries are never renamed, so d_lock is not needed */ |
3037 |
/* these dentries are never renamed, so d_lock is not needed */ |
3106 |
if (prepend(&end, &buflen, " (deleted)", 11) || |
3038 |
if (prepend(&end, &buflen, " (deleted)", 11) || |
3107 |
prepend(&end, &buflen, dentry->d_name.name, dentry->d_name.len) || |
3039 |
prepend_name(&end, &buflen, &dentry->d_name) || |
3108 |
prepend(&end, &buflen, "/", 1)) |
3040 |
prepend(&end, &buflen, "/", 1)) |
3109 |
end = ERR_PTR(-ENAMETOOLONG); |
3041 |
end = ERR_PTR(-ENAMETOOLONG); |
3110 |
return end; |
3042 |
return end; |
3111 |
} |
3043 |
} |
3112 |
|
3044 |
|
3113 |
/* |
3045 |
/* |
Lines 3115-3156
char *simple_dname(struct dentry *dentry, char *buffer, int buflen)
Link Here
|
3115 |
*/ |
3047 |
*/ |
3116 |
static char *__dentry_path(struct dentry *dentry, char *buf, int buflen) |
3048 |
static char *__dentry_path(struct dentry *dentry, char *buf, int buflen) |
3117 |
{ |
3049 |
{ |
3118 |
char *end, *retval; |
3050 |
char *end = buf + buflen; |
3119 |
int len, seq = 0; |
3051 |
char *retval; |
3120 |
int error = 0; |
|
|
3121 |
|
3052 |
|
3122 |
rcu_read_lock(); |
3053 |
prepend(&end, &buflen, "\0", 1); |
3123 |
restart: |
|
|
3124 |
end = buf + buflen; |
3125 |
len = buflen; |
3126 |
prepend(&end, &len, "\0", 1); |
3127 |
if (buflen < 1) |
3054 |
if (buflen < 1) |
3128 |
goto Elong; |
3055 |
goto Elong; |
3129 |
/* Get '/' right */ |
3056 |
/* Get '/' right */ |
3130 |
retval = end-1; |
3057 |
retval = end-1; |
3131 |
*retval = '/'; |
3058 |
*retval = '/'; |
3132 |
read_seqbegin_or_lock(&rename_lock, &seq); |
3059 |
|
3133 |
while (!IS_ROOT(dentry)) { |
3060 |
while (!IS_ROOT(dentry)) { |
3134 |
struct dentry *parent = dentry->d_parent; |
3061 |
struct dentry *parent = dentry->d_parent; |
3135 |
int error; |
3062 |
int error; |
3136 |
|
3063 |
|
3137 |
prefetch(parent); |
3064 |
prefetch(parent); |
3138 |
error = prepend_name(&end, &len, &dentry->d_name); |
3065 |
spin_lock(&dentry->d_lock); |
3139 |
if (error) |
3066 |
error = prepend_name(&end, &buflen, &dentry->d_name); |
3140 |
break; |
3067 |
spin_unlock(&dentry->d_lock); |
|
|
3068 |
if (error != 0 || prepend(&end, &buflen, "/", 1) != 0) |
3069 |
goto Elong; |
3141 |
|
3070 |
|
3142 |
retval = end; |
3071 |
retval = end; |
3143 |
dentry = parent; |
3072 |
dentry = parent; |
3144 |
} |
3073 |
} |
3145 |
if (!(seq & 1)) |
|
|
3146 |
rcu_read_unlock(); |
3147 |
if (need_seqretry(&rename_lock, seq)) { |
3148 |
seq = 1; |
3149 |
goto restart; |
3150 |
} |
3151 |
done_seqretry(&rename_lock, seq); |
3152 |
if (error) |
3153 |
goto Elong; |
3154 |
return retval; |
3074 |
return retval; |
3155 |
Elong: |
3075 |
Elong: |
3156 |
return ERR_PTR(-ENAMETOOLONG); |
3076 |
return ERR_PTR(-ENAMETOOLONG); |
Lines 3158-3164
Elong:
Link Here
|
3158 |
|
3078 |
|
3159 |
char *dentry_path_raw(struct dentry *dentry, char *buf, int buflen) |
3079 |
char *dentry_path_raw(struct dentry *dentry, char *buf, int buflen) |
3160 |
{ |
3080 |
{ |
3161 |
return __dentry_path(dentry, buf, buflen); |
3081 |
char *retval; |
|
|
3082 |
|
3083 |
write_seqlock(&rename_lock); |
3084 |
retval = __dentry_path(dentry, buf, buflen); |
3085 |
write_sequnlock(&rename_lock); |
3086 |
|
3087 |
return retval; |
3162 |
} |
3088 |
} |
3163 |
EXPORT_SYMBOL(dentry_path_raw); |
3089 |
EXPORT_SYMBOL(dentry_path_raw); |
3164 |
|
3090 |
|
Lines 3167-3172
char *dentry_path(struct dentry *dentry, char *buf, int buflen)
Link Here
|
3167 |
char *p = NULL; |
3093 |
char *p = NULL; |
3168 |
char *retval; |
3094 |
char *retval; |
3169 |
|
3095 |
|
|
|
3096 |
write_seqlock(&rename_lock); |
3170 |
if (d_unlinked(dentry)) { |
3097 |
if (d_unlinked(dentry)) { |
3171 |
p = buf + buflen; |
3098 |
p = buf + buflen; |
3172 |
if (prepend(&p, &buflen, "//deleted", 10) != 0) |
3099 |
if (prepend(&p, &buflen, "//deleted", 10) != 0) |
Lines 3174-3179
char *dentry_path(struct dentry *dentry, char *buf, int buflen)
Link Here
|
3174 |
buflen++; |
3101 |
buflen++; |
3175 |
} |
3102 |
} |
3176 |
retval = __dentry_path(dentry, buf, buflen); |
3103 |
retval = __dentry_path(dentry, buf, buflen); |
|
|
3104 |
write_sequnlock(&rename_lock); |
3177 |
if (!IS_ERR(retval) && p) |
3105 |
if (!IS_ERR(retval) && p) |
3178 |
*p = '/'; /* restore '/' overriden with '\0' */ |
3106 |
*p = '/'; /* restore '/' overriden with '\0' */ |
3179 |
return retval; |
3107 |
return retval; |
Lines 3225-3230
SYSCALL_DEFINE2(getcwd, char __user *, buf, unsigned long, size)
Link Here
|
3225 |
|
3153 |
|
3226 |
error = -ENOENT; |
3154 |
error = -ENOENT; |
3227 |
br_read_lock(&vfsmount_lock); |
3155 |
br_read_lock(&vfsmount_lock); |
|
|
3156 |
write_seqlock(&rename_lock); |
3228 |
if (!d_unlinked(pwd.dentry)) { |
3157 |
if (!d_unlinked(pwd.dentry)) { |
3229 |
unsigned long len; |
3158 |
unsigned long len; |
3230 |
char *cwd = page + PATH_MAX; |
3159 |
char *cwd = page + PATH_MAX; |
Lines 3232-3237
SYSCALL_DEFINE2(getcwd, char __user *, buf, unsigned long, size)
Link Here
|
3232 |
|
3161 |
|
3233 |
prepend(&cwd, &buflen, "\0", 1); |
3162 |
prepend(&cwd, &buflen, "\0", 1); |
3234 |
error = prepend_path(&pwd, &root, &cwd, &buflen); |
3163 |
error = prepend_path(&pwd, &root, &cwd, &buflen); |
|
|
3164 |
write_sequnlock(&rename_lock); |
3235 |
br_read_unlock(&vfsmount_lock); |
3165 |
br_read_unlock(&vfsmount_lock); |
3236 |
rcu_read_unlock(); |
3166 |
rcu_read_unlock(); |
3237 |
|
3167 |
|
Lines 3253-3258
SYSCALL_DEFINE2(getcwd, char __user *, buf, unsigned long, size)
Link Here
|
3253 |
error = -EFAULT; |
3183 |
error = -EFAULT; |
3254 |
} |
3184 |
} |
3255 |
} else { |
3185 |
} else { |
|
|
3186 |
write_sequnlock(&rename_lock); |
3256 |
br_read_unlock(&vfsmount_lock); |
3187 |
br_read_unlock(&vfsmount_lock); |
3257 |
rcu_read_unlock(); |
3188 |
rcu_read_unlock(); |
3258 |
} |
3189 |
} |
3259 |
- |
|
|