From patchwork Tue Jan 11 10:40:37 2011 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Suresh Jayaraman X-Patchwork-Id: 470641 Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by demeter1.kernel.org (8.14.4/8.14.3) with ESMTP id p0BAg9j4017185 for ; Tue, 11 Jan 2011 10:42:09 GMT Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1755628Ab1AKKlj (ORCPT ); Tue, 11 Jan 2011 05:41:39 -0500 Received: from victor.provo.novell.com ([137.65.250.26]:60001 "EHLO victor.provo.novell.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1755629Ab1AKKli (ORCPT ); Tue, 11 Jan 2011 05:41:38 -0500 Received: from jay-x201.blr.novell.com (prv-ext-foundry1int.gns.novell.com [137.65.251.240]) by victor.provo.novell.com with ESMTP; Tue, 11 Jan 2011 03:41:27 -0700 Message-ID: <4D2C33A5.9000801@suse.de> Date: Tue, 11 Jan 2011 16:10:37 +0530 From: Suresh Jayaraman User-Agent: Mozilla/5.0 (X11; U; Linux x86_64; en-US; rv:1.9.1.16) Gecko/20101125 SUSE/3.0.11 Thunderbird/3.0.11 ThunderBrowse/3.3.4 MIME-Version: 1.0 To: Steve French CC: linux-cifs@vger.kernel.org, Jeff Layton Subject: [PATCH] cifs: add mount option to handle stat() failures by 32-bit apps Sender: linux-cifs-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-cifs@vger.kernel.org X-Greylist: IP, sender and recipient auto-whitelisted, not delayed by milter-greylist-4.2.6 (demeter1.kernel.org [140.211.167.41]); Tue, 11 Jan 2011 10:42:33 +0000 (UTC) diff --git a/fs/cifs/cifs_fs_sb.h b/fs/cifs/cifs_fs_sb.h index 7852cd6..2563d26 100644 --- a/fs/cifs/cifs_fs_sb.h +++ b/fs/cifs/cifs_fs_sb.h @@ -40,6 +40,7 @@ #define CIFS_MOUNT_FSCACHE 0x8000 /* local caching enabled */ #define CIFS_MOUNT_MF_SYMLINKS 0x10000 /* Minshall+French Symlinks enabled */ #define CIFS_MOUNT_MULTIUSER 0x20000 /* multiuser mount */ +#define CIFS_MOUNT_32BIT_INODES 0x40000 /* squash to 32-bits */ struct cifs_sb_info { struct rb_root tlink_tree; diff --git a/fs/cifs/cifsfs.c b/fs/cifs/cifsfs.c index 5e7075d..6b370e8 100644 --- a/fs/cifs/cifsfs.c +++ b/fs/cifs/cifsfs.c @@ -473,6 +473,10 @@ cifs_show_options(struct seq_file *s, struct vfsmount *m) seq_printf(s, ",mfsymlinks"); if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_FSCACHE) seq_printf(s, ",fsc"); + if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_32BIT_INODES) + seq_printf(s, ",noinode64"); + else + seq_printf(s, ",inode64"); seq_printf(s, ",rsize=%d", cifs_sb->rsize); seq_printf(s, ",wsize=%d", cifs_sb->wsize); diff --git a/fs/cifs/cifsfs.h b/fs/cifs/cifsfs.h index 897b2b2..e01d9e3 100644 --- a/fs/cifs/cifsfs.h +++ b/fs/cifs/cifsfs.h @@ -22,6 +22,8 @@ #ifndef _CIFSFS_H #define _CIFSFS_H +#include + #define ROOT_I 2 /* @@ -37,6 +39,20 @@ cifs_uniqueid_to_ino_t(u64 fileid) return ino; } +static inline u64 +cifs_compat_user_ino64(u64 fileid) +{ +#ifdef CONFIG_COMPAT + compat_ulong_t ino; +#else + unsigned long ino; +#endif + ino = fileid; + if (sizeof(ino) < sizeof(u64)) + ino ^= fileid >> (sizeof(u64)-sizeof(ino)) * 8; + return ino; +} + extern struct file_system_type cifs_fs_type; extern const struct address_space_operations cifs_addr_ops; extern const struct address_space_operations cifs_addr_ops_smallbuf; diff --git a/fs/cifs/connect.c b/fs/cifs/connect.c index a65d311..7fdb361 100644 --- a/fs/cifs/connect.c +++ b/fs/cifs/connect.c @@ -101,6 +101,7 @@ struct smb_vol { bool fsc:1; /* enable fscache */ bool mfsymlinks:1; /* use Minshall+French Symlinks */ bool multiuser:1; + bool inode64:1; unsigned int rsize; unsigned int wsize; bool sockopt_tcp_nodelay:1; @@ -836,6 +837,8 @@ cifs_parse_mount_options(char *options, const char *devname, vol->posix_paths = 1; /* default to using server inode numbers where available */ vol->server_ino = 1; + /* default to support 64-bit inode numbers */ + vol->inode64 = 1; vol->actimeo = CIFS_DEF_ACTIMEO; @@ -1368,6 +1371,10 @@ cifs_parse_mount_options(char *options, const char *devname, vol->mfsymlinks = true; } else if (strnicmp(data, "multiuser", 8) == 0) { vol->multiuser = true; + } else if (strnicmp(data, "inode64", 7) == 0) { + vol->inode64 = 1; + } else if (strnicmp(data, "noinode64", 9) == 0) { + vol->inode64 = 0; } else printk(KERN_WARNING "CIFS: Unknown mount option %s\n", data); @@ -2578,6 +2585,9 @@ static void setup_cifs_sb(struct smb_vol *pvolume_info, if (pvolume_info->multiuser) cifs_sb->mnt_cifs_flags |= (CIFS_MOUNT_MULTIUSER | CIFS_MOUNT_NO_PERM); + if (!pvolume_info->inode64) + cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_32BIT_INODES; + if (pvolume_info->direct_io) { cFYI(1, "mounting share using direct i/o"); cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_DIRECT_IO; diff --git a/fs/cifs/inode.c b/fs/cifs/inode.c index 0c7e369..b31c8d9 100644 --- a/fs/cifs/inode.c +++ b/fs/cifs/inode.c @@ -1791,6 +1791,10 @@ int cifs_getattr(struct vfsmount *mnt, struct dentry *dentry, if (!(cifs_sb->mnt_cifs_flags & CIFS_MOUNT_OVERR_GID)) stat->gid = current_fsgid(); } + + /* squash to 32-bits if 'noinode64' option is enabled */ + if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_32BIT_INODES) + stat->ino = cifs_uniqueid_to_ino_t(stat->ino); } return err; } diff --git a/fs/cifs/readdir.c b/fs/cifs/readdir.c index 76b1b37..b902fd0 100644 --- a/fs/cifs/readdir.c +++ b/fs/cifs/readdir.c @@ -754,7 +754,10 @@ static int cifs_filldir(char *pfindEntry, struct file *file, filldir_t filldir, */ fattr.cf_flags |= CIFS_FATTR_NEED_REVAL; - ino = cifs_uniqueid_to_ino_t(fattr.cf_uniqueid); + if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_32BIT_INODES) + ino = cifs_compat_user_ino64(fattr.cf_uniqueid); + else + ino = cifs_uniqueid_to_ino_t(fattr.cf_uniqueid); tmp_dentry = cifs_readdir_lookup(file->f_dentry, &qstring, &fattr); rc = filldir(direntry, qstring.name, qstring.len, file->f_pos,