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 | |
| 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>
| -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 ebafa65a29b..cbe875d3a52 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 60456361e07..b54c97da1c4 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 9c5085465a6..e39ea78c489 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 20b907d76ae..5405c903704 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 | /* |
