diff --git a/lustre/include/linux/lvfs.h b/lustre/include/linux/lvfs.h index 801281bfe9ca627cc4cabc0314c6a31fe53fc4e0..225204b319e375cd85ef88381b04c5b9d5e1c2d2 100644 --- a/lustre/include/linux/lvfs.h +++ b/lustre/include/linux/lvfs.h @@ -110,6 +110,10 @@ int lustre_fread(struct file *file, void *buf, int len, loff_t *off); int lustre_fwrite(struct file *file, const void *buf, int len, loff_t *off); int lustre_fsync(struct file *file); long l_readdir(struct file * file, struct list_head *dentry_list); +int l_notify_change(struct vfsmount *mnt, struct dentry *dchild, + struct iattr *newattrs); +int simple_truncate(struct dentry *dir, struct vfsmount *mnt, + char *name, loff_t length); static inline void l_dput(struct dentry *de) { diff --git a/lustre/lvfs/lvfs_linux.c b/lustre/lvfs/lvfs_linux.c index 8f9eaaa01762364a9b1e4c2b35310bca2dd3b9b4..631d8bcf0be4aab779a838caa94c967e0ceff20f 100644 --- a/lustre/lvfs/lvfs_linux.c +++ b/lustre/lvfs/lvfs_linux.c @@ -473,6 +473,57 @@ long l_readdir(struct file *file, struct list_head *dentry_list) } EXPORT_SYMBOL(l_readdir); +int l_notify_change(struct vfsmount *mnt, struct dentry *dchild, + struct iattr *newattrs) +{ + int rc; + + LOCK_INODE_MUTEX(dchild->d_inode); +#ifdef HAVE_SECURITY_PLUG + rc = notify_change(dchild, mnt, newattrs); +#else + rc = notify_change(dchild, newattrs); +#endif + UNLOCK_INODE_MUTEX(dchild->d_inode); + return rc; +} +EXPORT_SYMBOL(l_notify_change); + +/* utility to truncate a file */ +int simple_truncate(struct dentry *dir, struct vfsmount *mnt, + char *name, loff_t length) +{ + struct dentry *dchild; + struct iattr newattrs; + int err = 0; + ENTRY; + + CDEBUG(D_INODE, "truncating file %.*s to %lld\n", (int)strlen(name), + name, (long long)length); + dchild = ll_lookup_one_len(name, dir, strlen(name)); + if (IS_ERR(dchild)) + GOTO(out, err = PTR_ERR(dchild)); + + if (dchild->d_inode) { + int old_mode = dchild->d_inode->i_mode; + if (S_ISDIR(old_mode)) { + CERROR("found %s (%lu/%u) is mode %o\n", name, + dchild->d_inode->i_ino, + dchild->d_inode->i_generation, old_mode); + GOTO(out_dput, err = -EISDIR); + } + + newattrs.ia_size = length; + newattrs.ia_valid = ATTR_SIZE; + err = l_notify_change(mnt, dchild, &newattrs); + } + EXIT; +out_dput: + dput(dchild); +out: + return err; +} +EXPORT_SYMBOL(simple_truncate); #ifdef LUSTRE_KERNEL_VERSION #ifndef HAVE_CLEAR_RDONLY_ON_PUT diff --git a/lustre/obdclass/obd_mount.c b/lustre/obdclass/obd_mount.c index d7e0aacbd88f43e045c18831dbfa7829033659f3..df95ebab9052e305ac0520ba5f7378eda8da1e0d 100644 --- a/lustre/obdclass/obd_mount.c +++ b/lustre/obdclass/obd_mount.c @@ -1321,6 +1321,10 @@ static struct vfsmount *server_kernel_mount(struct super_block *sb) GOTO(out_free, rc); } + if (lmd->lmd_flags & LMD_FLG_ABORT_RECOV) + simple_truncate(mnt->mnt_sb->s_root, mnt, LAST_RCVD, + LR_CLIENT_START); + OBD_PAGE_FREE(__page); lsi->lsi_ldd = ldd; /* freed at lsi cleanup */ CDEBUG(D_SUPER, "%s: mnt = %p\n", lmd->lmd_dev, mnt);