diff options
Diffstat (limited to 'fs')
| -rw-r--r-- | fs/9p/vfs_dir.c | 2 | ||||
| -rw-r--r-- | fs/gfs2/dir.c | 31 | ||||
| -rw-r--r-- | fs/sysfs/symlink.c | 26 |
3 files changed, 46 insertions, 13 deletions
diff --git a/fs/9p/vfs_dir.c b/fs/9p/vfs_dir.c index d61e3b28ce37..36d961f342af 100644 --- a/fs/9p/vfs_dir.c +++ b/fs/9p/vfs_dir.c | |||
| @@ -146,7 +146,7 @@ static int v9fs_dir_readdir(struct file *filp, void *dirent, filldir_t filldir) | |||
| 146 | while (rdir->head < rdir->tail) { | 146 | while (rdir->head < rdir->tail) { |
| 147 | p9stat_init(&st); | 147 | p9stat_init(&st); |
| 148 | err = p9stat_read(rdir->buf + rdir->head, | 148 | err = p9stat_read(rdir->buf + rdir->head, |
| 149 | buflen - rdir->head, &st, | 149 | rdir->tail - rdir->head, &st, |
| 150 | fid->clnt->proto_version); | 150 | fid->clnt->proto_version); |
| 151 | if (err) { | 151 | if (err) { |
| 152 | P9_DPRINTK(P9_DEBUG_VFS, "returned %d\n", err); | 152 | P9_DPRINTK(P9_DEBUG_VFS, "returned %d\n", err); |
diff --git a/fs/gfs2/dir.c b/fs/gfs2/dir.c index 26ca3361a8bc..6b48d7c268b2 100644 --- a/fs/gfs2/dir.c +++ b/fs/gfs2/dir.c | |||
| @@ -1231,6 +1231,25 @@ static int do_filldir_main(struct gfs2_inode *dip, u64 *offset, | |||
| 1231 | return 0; | 1231 | return 0; |
| 1232 | } | 1232 | } |
| 1233 | 1233 | ||
| 1234 | static void *gfs2_alloc_sort_buffer(unsigned size) | ||
| 1235 | { | ||
| 1236 | void *ptr = NULL; | ||
| 1237 | |||
| 1238 | if (size < KMALLOC_MAX_SIZE) | ||
| 1239 | ptr = kmalloc(size, GFP_NOFS | __GFP_NOWARN); | ||
| 1240 | if (!ptr) | ||
| 1241 | ptr = __vmalloc(size, GFP_NOFS, PAGE_KERNEL); | ||
| 1242 | return ptr; | ||
| 1243 | } | ||
| 1244 | |||
| 1245 | static void gfs2_free_sort_buffer(void *ptr) | ||
| 1246 | { | ||
| 1247 | if (is_vmalloc_addr(ptr)) | ||
| 1248 | vfree(ptr); | ||
| 1249 | else | ||
| 1250 | kfree(ptr); | ||
| 1251 | } | ||
| 1252 | |||
| 1234 | static int gfs2_dir_read_leaf(struct inode *inode, u64 *offset, void *opaque, | 1253 | static int gfs2_dir_read_leaf(struct inode *inode, u64 *offset, void *opaque, |
| 1235 | filldir_t filldir, int *copied, unsigned *depth, | 1254 | filldir_t filldir, int *copied, unsigned *depth, |
| 1236 | u64 leaf_no) | 1255 | u64 leaf_no) |
| @@ -1271,7 +1290,7 @@ static int gfs2_dir_read_leaf(struct inode *inode, u64 *offset, void *opaque, | |||
| 1271 | * 99 is the maximum number of entries that can fit in a single | 1290 | * 99 is the maximum number of entries that can fit in a single |
| 1272 | * leaf block. | 1291 | * leaf block. |
| 1273 | */ | 1292 | */ |
| 1274 | larr = vmalloc((leaves + entries + 99) * sizeof(void *)); | 1293 | larr = gfs2_alloc_sort_buffer((leaves + entries + 99) * sizeof(void *)); |
| 1275 | if (!larr) | 1294 | if (!larr) |
| 1276 | goto out; | 1295 | goto out; |
| 1277 | darr = (const struct gfs2_dirent **)(larr + leaves); | 1296 | darr = (const struct gfs2_dirent **)(larr + leaves); |
| @@ -1282,7 +1301,7 @@ static int gfs2_dir_read_leaf(struct inode *inode, u64 *offset, void *opaque, | |||
| 1282 | do { | 1301 | do { |
| 1283 | error = get_leaf(ip, lfn, &bh); | 1302 | error = get_leaf(ip, lfn, &bh); |
| 1284 | if (error) | 1303 | if (error) |
| 1285 | goto out_kfree; | 1304 | goto out_free; |
| 1286 | lf = (struct gfs2_leaf *)bh->b_data; | 1305 | lf = (struct gfs2_leaf *)bh->b_data; |
| 1287 | lfn = be64_to_cpu(lf->lf_next); | 1306 | lfn = be64_to_cpu(lf->lf_next); |
| 1288 | if (lf->lf_entries) { | 1307 | if (lf->lf_entries) { |
| @@ -1291,7 +1310,7 @@ static int gfs2_dir_read_leaf(struct inode *inode, u64 *offset, void *opaque, | |||
| 1291 | gfs2_dirent_gather, NULL, &g); | 1310 | gfs2_dirent_gather, NULL, &g); |
| 1292 | error = PTR_ERR(dent); | 1311 | error = PTR_ERR(dent); |
| 1293 | if (IS_ERR(dent)) | 1312 | if (IS_ERR(dent)) |
| 1294 | goto out_kfree; | 1313 | goto out_free; |
| 1295 | if (entries2 != g.offset) { | 1314 | if (entries2 != g.offset) { |
| 1296 | fs_warn(sdp, "Number of entries corrupt in dir " | 1315 | fs_warn(sdp, "Number of entries corrupt in dir " |
| 1297 | "leaf %llu, entries2 (%u) != " | 1316 | "leaf %llu, entries2 (%u) != " |
| @@ -1300,7 +1319,7 @@ static int gfs2_dir_read_leaf(struct inode *inode, u64 *offset, void *opaque, | |||
| 1300 | entries2, g.offset); | 1319 | entries2, g.offset); |
| 1301 | 1320 | ||
| 1302 | error = -EIO; | 1321 | error = -EIO; |
| 1303 | goto out_kfree; | 1322 | goto out_free; |
| 1304 | } | 1323 | } |
| 1305 | error = 0; | 1324 | error = 0; |
| 1306 | larr[leaf++] = bh; | 1325 | larr[leaf++] = bh; |
| @@ -1312,10 +1331,10 @@ static int gfs2_dir_read_leaf(struct inode *inode, u64 *offset, void *opaque, | |||
| 1312 | BUG_ON(entries2 != entries); | 1331 | BUG_ON(entries2 != entries); |
| 1313 | error = do_filldir_main(ip, offset, opaque, filldir, darr, | 1332 | error = do_filldir_main(ip, offset, opaque, filldir, darr, |
| 1314 | entries, copied); | 1333 | entries, copied); |
| 1315 | out_kfree: | 1334 | out_free: |
| 1316 | for(i = 0; i < leaf; i++) | 1335 | for(i = 0; i < leaf; i++) |
| 1317 | brelse(larr[i]); | 1336 | brelse(larr[i]); |
| 1318 | vfree(larr); | 1337 | gfs2_free_sort_buffer(larr); |
| 1319 | out: | 1338 | out: |
| 1320 | return error; | 1339 | return error; |
| 1321 | } | 1340 | } |
diff --git a/fs/sysfs/symlink.c b/fs/sysfs/symlink.c index f71246bebfe4..a7ac78f8e67a 100644 --- a/fs/sysfs/symlink.c +++ b/fs/sysfs/symlink.c | |||
| @@ -28,6 +28,7 @@ static int sysfs_do_create_link(struct kobject *kobj, struct kobject *target, | |||
| 28 | struct sysfs_dirent *target_sd = NULL; | 28 | struct sysfs_dirent *target_sd = NULL; |
| 29 | struct sysfs_dirent *sd = NULL; | 29 | struct sysfs_dirent *sd = NULL; |
| 30 | struct sysfs_addrm_cxt acxt; | 30 | struct sysfs_addrm_cxt acxt; |
| 31 | enum kobj_ns_type ns_type; | ||
| 31 | int error; | 32 | int error; |
| 32 | 33 | ||
| 33 | BUG_ON(!name); | 34 | BUG_ON(!name); |
| @@ -58,16 +59,29 @@ static int sysfs_do_create_link(struct kobject *kobj, struct kobject *target, | |||
| 58 | if (!sd) | 59 | if (!sd) |
| 59 | goto out_put; | 60 | goto out_put; |
| 60 | 61 | ||
| 61 | if (sysfs_ns_type(parent_sd)) | 62 | ns_type = sysfs_ns_type(parent_sd); |
| 63 | if (ns_type) | ||
| 62 | sd->s_ns = target->ktype->namespace(target); | 64 | sd->s_ns = target->ktype->namespace(target); |
| 63 | sd->s_symlink.target_sd = target_sd; | 65 | sd->s_symlink.target_sd = target_sd; |
| 64 | target_sd = NULL; /* reference is now owned by the symlink */ | 66 | target_sd = NULL; /* reference is now owned by the symlink */ |
| 65 | 67 | ||
| 66 | sysfs_addrm_start(&acxt, parent_sd); | 68 | sysfs_addrm_start(&acxt, parent_sd); |
| 67 | if (warn) | 69 | /* Symlinks must be between directories with the same ns_type */ |
| 68 | error = sysfs_add_one(&acxt, sd); | 70 | if (!ns_type || |
| 69 | else | 71 | (ns_type == sysfs_ns_type(sd->s_symlink.target_sd->s_parent))) { |
| 70 | error = __sysfs_add_one(&acxt, sd); | 72 | if (warn) |
| 73 | error = sysfs_add_one(&acxt, sd); | ||
| 74 | else | ||
| 75 | error = __sysfs_add_one(&acxt, sd); | ||
| 76 | } else { | ||
| 77 | error = -EINVAL; | ||
| 78 | WARN(1, KERN_WARNING | ||
| 79 | "sysfs: symlink across ns_types %s/%s -> %s/%s\n", | ||
| 80 | parent_sd->s_name, | ||
| 81 | sd->s_name, | ||
| 82 | sd->s_symlink.target_sd->s_parent->s_name, | ||
| 83 | sd->s_symlink.target_sd->s_name); | ||
| 84 | } | ||
| 71 | sysfs_addrm_finish(&acxt); | 85 | sysfs_addrm_finish(&acxt); |
| 72 | 86 | ||
| 73 | if (error) | 87 | if (error) |
| @@ -122,7 +136,7 @@ void sysfs_delete_link(struct kobject *kobj, struct kobject *targ, | |||
| 122 | { | 136 | { |
| 123 | const void *ns = NULL; | 137 | const void *ns = NULL; |
| 124 | spin_lock(&sysfs_assoc_lock); | 138 | spin_lock(&sysfs_assoc_lock); |
| 125 | if (targ->sd) | 139 | if (targ->sd && sysfs_ns_type(kobj->sd)) |
| 126 | ns = targ->sd->s_ns; | 140 | ns = targ->sd->s_ns; |
| 127 | spin_unlock(&sysfs_assoc_lock); | 141 | spin_unlock(&sysfs_assoc_lock); |
| 128 | sysfs_hash_and_remove(kobj->sd, ns, name); | 142 | sysfs_hash_and_remove(kobj->sd, ns, name); |
