diff options
author | Yehuda Sadeh <yehuda@hq.newdream.net> | 2011-01-21 19:44:03 -0500 |
---|---|---|
committer | Sage Weil <sage@newdream.net> | 2011-03-21 15:24:22 -0400 |
commit | ad1fee96cbaf873520064252c5dc3212c9844861 (patch) | |
tree | bce9fcd824af836279a6dd10007430cc3872cb3a /fs | |
parent | 483fac71485e5063ff4033b6dc7d91567f1b6ff1 (diff) |
ceph: add ino32 mount option
The ino32 mount option forces the ceph fs to report 32 bit
ino values. This is useful for 64 bit kernels with 32 bit userspace.
Signed-off-by: Yehuda Sadeh <yehuda@hq.newdream.net>
Diffstat (limited to 'fs')
-rw-r--r-- | fs/ceph/dir.c | 11 | ||||
-rw-r--r-- | fs/ceph/inode.c | 9 | ||||
-rw-r--r-- | fs/ceph/super.c | 5 | ||||
-rw-r--r-- | fs/ceph/super.h | 65 |
4 files changed, 65 insertions, 25 deletions
diff --git a/fs/ceph/dir.c b/fs/ceph/dir.c index ebafa65a29b6..cbe875d3a522 100644 --- a/fs/ceph/dir.c +++ b/fs/ceph/dir.c | |||
@@ -161,7 +161,7 @@ more: | |||
161 | filp->f_pos = di->offset; | 161 | filp->f_pos = di->offset; |
162 | err = filldir(dirent, dentry->d_name.name, | 162 | err = filldir(dirent, dentry->d_name.name, |
163 | dentry->d_name.len, di->offset, | 163 | dentry->d_name.len, di->offset, |
164 | dentry->d_inode->i_ino, | 164 | ceph_translate_ino(dentry->d_sb, dentry->d_inode->i_ino), |
165 | dentry->d_inode->i_mode >> 12); | 165 | dentry->d_inode->i_mode >> 12); |
166 | 166 | ||
167 | if (last) { | 167 | if (last) { |
@@ -245,15 +245,17 @@ static int ceph_readdir(struct file *filp, void *dirent, filldir_t filldir) | |||
245 | 245 | ||
246 | dout("readdir off 0 -> '.'\n"); | 246 | dout("readdir off 0 -> '.'\n"); |
247 | if (filldir(dirent, ".", 1, ceph_make_fpos(0, 0), | 247 | if (filldir(dirent, ".", 1, ceph_make_fpos(0, 0), |
248 | inode->i_ino, inode->i_mode >> 12) < 0) | 248 | ceph_translate_ino(inode->i_sb, inode->i_ino), |
249 | inode->i_mode >> 12) < 0) | ||
249 | return 0; | 250 | return 0; |
250 | filp->f_pos = 1; | 251 | filp->f_pos = 1; |
251 | off = 1; | 252 | off = 1; |
252 | } | 253 | } |
253 | if (filp->f_pos == 1) { | 254 | if (filp->f_pos == 1) { |
255 | ino_t ino = filp->f_dentry->d_parent->d_inode->i_ino; | ||
254 | dout("readdir off 1 -> '..'\n"); | 256 | dout("readdir off 1 -> '..'\n"); |
255 | if (filldir(dirent, "..", 2, ceph_make_fpos(0, 1), | 257 | if (filldir(dirent, "..", 2, ceph_make_fpos(0, 1), |
256 | filp->f_dentry->d_parent->d_inode->i_ino, | 258 | ceph_translate_ino(inode->i_sb, ino), |
257 | inode->i_mode >> 12) < 0) | 259 | inode->i_mode >> 12) < 0) |
258 | return 0; | 260 | return 0; |
259 | filp->f_pos = 2; | 261 | filp->f_pos = 2; |
@@ -377,7 +379,8 @@ more: | |||
377 | if (filldir(dirent, | 379 | if (filldir(dirent, |
378 | rinfo->dir_dname[off - fi->offset], | 380 | rinfo->dir_dname[off - fi->offset], |
379 | rinfo->dir_dname_len[off - fi->offset], | 381 | rinfo->dir_dname_len[off - fi->offset], |
380 | pos, ino, ftype) < 0) { | 382 | pos, |
383 | ceph_translate_ino(inode->i_sb, ino), ftype) < 0) { | ||
381 | dout("filldir stopping us...\n"); | 384 | dout("filldir stopping us...\n"); |
382 | return 0; | 385 | return 0; |
383 | } | 386 | } |
diff --git a/fs/ceph/inode.c b/fs/ceph/inode.c index 60456361e07d..b54c97da1c43 100644 --- a/fs/ceph/inode.c +++ b/fs/ceph/inode.c | |||
@@ -36,6 +36,13 @@ static void ceph_vmtruncate_work(struct work_struct *work); | |||
36 | /* | 36 | /* |
37 | * find or create an inode, given the ceph ino number | 37 | * find or create an inode, given the ceph ino number |
38 | */ | 38 | */ |
39 | static int ceph_set_ino_cb(struct inode *inode, void *data) | ||
40 | { | ||
41 | ceph_inode(inode)->i_vino = *(struct ceph_vino *)data; | ||
42 | inode->i_ino = ceph_vino_to_ino(*(struct ceph_vino *)data); | ||
43 | return 0; | ||
44 | } | ||
45 | |||
39 | struct inode *ceph_get_inode(struct super_block *sb, struct ceph_vino vino) | 46 | struct inode *ceph_get_inode(struct super_block *sb, struct ceph_vino vino) |
40 | { | 47 | { |
41 | struct inode *inode; | 48 | struct inode *inode; |
@@ -1809,7 +1816,7 @@ int ceph_getattr(struct vfsmount *mnt, struct dentry *dentry, | |||
1809 | err = ceph_do_getattr(inode, CEPH_STAT_CAP_INODE_ALL); | 1816 | err = ceph_do_getattr(inode, CEPH_STAT_CAP_INODE_ALL); |
1810 | if (!err) { | 1817 | if (!err) { |
1811 | generic_fillattr(inode, stat); | 1818 | generic_fillattr(inode, stat); |
1812 | stat->ino = inode->i_ino; | 1819 | stat->ino = ceph_translate_ino(inode->i_sb, inode->i_ino); |
1813 | if (ceph_snap(inode) != CEPH_NOSNAP) | 1820 | if (ceph_snap(inode) != CEPH_NOSNAP) |
1814 | stat->dev = ceph_snap(inode); | 1821 | stat->dev = ceph_snap(inode); |
1815 | else | 1822 | else |
diff --git a/fs/ceph/super.c b/fs/ceph/super.c index 9c5085465a63..e39ea78c4894 100644 --- a/fs/ceph/super.c +++ b/fs/ceph/super.c | |||
@@ -131,6 +131,7 @@ enum { | |||
131 | Opt_rbytes, | 131 | Opt_rbytes, |
132 | Opt_norbytes, | 132 | Opt_norbytes, |
133 | Opt_noasyncreaddir, | 133 | Opt_noasyncreaddir, |
134 | Opt_ino32, | ||
134 | }; | 135 | }; |
135 | 136 | ||
136 | static match_table_t fsopt_tokens = { | 137 | static match_table_t fsopt_tokens = { |
@@ -150,6 +151,7 @@ static match_table_t fsopt_tokens = { | |||
150 | {Opt_rbytes, "rbytes"}, | 151 | {Opt_rbytes, "rbytes"}, |
151 | {Opt_norbytes, "norbytes"}, | 152 | {Opt_norbytes, "norbytes"}, |
152 | {Opt_noasyncreaddir, "noasyncreaddir"}, | 153 | {Opt_noasyncreaddir, "noasyncreaddir"}, |
154 | {Opt_ino32, "ino32"}, | ||
153 | {-1, NULL} | 155 | {-1, NULL} |
154 | }; | 156 | }; |
155 | 157 | ||
@@ -225,6 +227,9 @@ static int parse_fsopt_token(char *c, void *private) | |||
225 | case Opt_noasyncreaddir: | 227 | case Opt_noasyncreaddir: |
226 | fsopt->flags |= CEPH_MOUNT_OPT_NOASYNCREADDIR; | 228 | fsopt->flags |= CEPH_MOUNT_OPT_NOASYNCREADDIR; |
227 | break; | 229 | break; |
230 | case Opt_ino32: | ||
231 | fsopt->flags |= CEPH_MOUNT_OPT_INO32; | ||
232 | break; | ||
228 | default: | 233 | default: |
229 | BUG_ON(token); | 234 | BUG_ON(token); |
230 | } | 235 | } |
diff --git a/fs/ceph/super.h b/fs/ceph/super.h index 20b907d76ae2..5405c903704e 100644 --- a/fs/ceph/super.h +++ b/fs/ceph/super.h | |||
@@ -27,6 +27,7 @@ | |||
27 | #define CEPH_MOUNT_OPT_DIRSTAT (1<<4) /* `cat dirname` for stats */ | 27 | #define CEPH_MOUNT_OPT_DIRSTAT (1<<4) /* `cat dirname` for stats */ |
28 | #define CEPH_MOUNT_OPT_RBYTES (1<<5) /* dir st_bytes = rbytes */ | 28 | #define CEPH_MOUNT_OPT_RBYTES (1<<5) /* dir st_bytes = rbytes */ |
29 | #define CEPH_MOUNT_OPT_NOASYNCREADDIR (1<<7) /* no dcache readdir */ | 29 | #define CEPH_MOUNT_OPT_NOASYNCREADDIR (1<<7) /* no dcache readdir */ |
30 | #define CEPH_MOUNT_OPT_INO32 (1<<8) /* 32 bit inos */ | ||
30 | 31 | ||
31 | #define CEPH_MOUNT_OPT_DEFAULT (CEPH_MOUNT_OPT_RBYTES) | 32 | #define CEPH_MOUNT_OPT_DEFAULT (CEPH_MOUNT_OPT_RBYTES) |
32 | 33 | ||
@@ -319,6 +320,16 @@ static inline struct ceph_inode_info *ceph_inode(struct inode *inode) | |||
319 | return container_of(inode, struct ceph_inode_info, vfs_inode); | 320 | return container_of(inode, struct ceph_inode_info, vfs_inode); |
320 | } | 321 | } |
321 | 322 | ||
323 | static inline struct ceph_fs_client *ceph_inode_to_client(struct inode *inode) | ||
324 | { | ||
325 | return (struct ceph_fs_client *)inode->i_sb->s_fs_info; | ||
326 | } | ||
327 | |||
328 | static inline struct ceph_fs_client *ceph_sb_to_client(struct super_block *sb) | ||
329 | { | ||
330 | return (struct ceph_fs_client *)sb->s_fs_info; | ||
331 | } | ||
332 | |||
322 | static inline struct ceph_vino ceph_vino(struct inode *inode) | 333 | static inline struct ceph_vino ceph_vino(struct inode *inode) |
323 | { | 334 | { |
324 | return ceph_inode(inode)->i_vino; | 335 | return ceph_inode(inode)->i_vino; |
@@ -327,19 +338,49 @@ static inline struct ceph_vino ceph_vino(struct inode *inode) | |||
327 | /* | 338 | /* |
328 | * ino_t is <64 bits on many architectures, blech. | 339 | * ino_t is <64 bits on many architectures, blech. |
329 | * | 340 | * |
330 | * don't include snap in ino hash, at least for now. | 341 | * i_ino (kernel inode) st_ino (userspace) |
342 | * i386 32 32 | ||
343 | * x86_64+ino32 64 32 | ||
344 | * x86_64 64 64 | ||
345 | */ | ||
346 | static inline u32 ceph_ino_to_ino32(ino_t ino) | ||
347 | { | ||
348 | ino ^= ino >> (sizeof(ino) * 8 - 32); | ||
349 | if (!ino) | ||
350 | ino = 1; | ||
351 | return ino; | ||
352 | } | ||
353 | |||
354 | /* | ||
355 | * kernel i_ino value | ||
331 | */ | 356 | */ |
332 | static inline ino_t ceph_vino_to_ino(struct ceph_vino vino) | 357 | static inline ino_t ceph_vino_to_ino(struct ceph_vino vino) |
333 | { | 358 | { |
334 | ino_t ino = (ino_t)vino.ino; /* ^ (vino.snap << 20); */ | 359 | ino_t ino = (ino_t)vino.ino; /* ^ (vino.snap << 20); */ |
335 | #if BITS_PER_LONG == 32 | 360 | #if BITS_PER_LONG == 32 |
336 | ino ^= vino.ino >> (sizeof(u64)-sizeof(ino_t)) * 8; | 361 | ino = ceph_ino_to_ino32(ino); |
337 | if (!ino) | ||
338 | ino = 1; | ||
339 | #endif | 362 | #endif |
340 | return ino; | 363 | return ino; |
341 | } | 364 | } |
342 | 365 | ||
366 | /* | ||
367 | * user-visible ino (stat, filldir) | ||
368 | */ | ||
369 | #if BITS_PER_LONG == 32 | ||
370 | static inline ino_t ceph_translate_ino(struct super_block *sb, ino_t ino) | ||
371 | { | ||
372 | return ino; | ||
373 | } | ||
374 | #else | ||
375 | static inline ino_t ceph_translate_ino(struct super_block *sb, ino_t ino) | ||
376 | { | ||
377 | if (ceph_test_mount_opt(ceph_sb_to_client(sb), INO32)) | ||
378 | ino = ceph_ino_to_ino32(ino); | ||
379 | return ino; | ||
380 | } | ||
381 | #endif | ||
382 | |||
383 | |||
343 | /* for printf-style formatting */ | 384 | /* for printf-style formatting */ |
344 | #define ceph_vinop(i) ceph_inode(i)->i_vino.ino, ceph_inode(i)->i_vino.snap | 385 | #define ceph_vinop(i) ceph_inode(i)->i_vino.ino, ceph_inode(i)->i_vino.snap |
345 | 386 | ||
@@ -428,13 +469,6 @@ static inline loff_t ceph_make_fpos(unsigned frag, unsigned off) | |||
428 | return ((loff_t)frag << 32) | (loff_t)off; | 469 | return ((loff_t)frag << 32) | (loff_t)off; |
429 | } | 470 | } |
430 | 471 | ||
431 | static inline int ceph_set_ino_cb(struct inode *inode, void *data) | ||
432 | { | ||
433 | ceph_inode(inode)->i_vino = *(struct ceph_vino *)data; | ||
434 | inode->i_ino = ceph_vino_to_ino(*(struct ceph_vino *)data); | ||
435 | return 0; | ||
436 | } | ||
437 | |||
438 | /* | 472 | /* |
439 | * caps helpers | 473 | * caps helpers |
440 | */ | 474 | */ |
@@ -503,15 +537,6 @@ extern void ceph_reservation_status(struct ceph_fs_client *client, | |||
503 | int *total, int *avail, int *used, | 537 | int *total, int *avail, int *used, |
504 | int *reserved, int *min); | 538 | int *reserved, int *min); |
505 | 539 | ||
506 | static inline struct ceph_fs_client *ceph_inode_to_client(struct inode *inode) | ||
507 | { | ||
508 | return (struct ceph_fs_client *)inode->i_sb->s_fs_info; | ||
509 | } | ||
510 | |||
511 | static inline struct ceph_fs_client *ceph_sb_to_client(struct super_block *sb) | ||
512 | { | ||
513 | return (struct ceph_fs_client *)sb->s_fs_info; | ||
514 | } | ||
515 | 540 | ||
516 | 541 | ||
517 | /* | 542 | /* |